Search code examples
ormlite-servicestack

How to resolve a named OrmLiteConnectionFactory in a service at run-time?


I've created an OrmLiteConnectionFactory in my apphost and added 2 named connections, "ConnOne" and "ConnTwo" through RegisterConnection. I wish to use either one interchangeable based on a property in the service that won't be resolved until run-time.

var factory = new OrmLiteConnectionFactory();
        factory.RegisterConnection("ConnOne", Config.SqlServerTenantOne, SqlServerDialect.Provider);
        factory.RegisterConnection("ConnTwo", Config.SqlServerTenantTwo, SqlServerDialect.Provider);



public class Repository : IDisposable {

    public string Tenant { get; set; }

    public IDbConnectionFactory DbFactory { get; set; } //not injected

    IDbConnection db;
    IDbConnection Db 
    { 
        get 
        {
            return db ?? db = DbFactory.OpenDbConnection(Tenant); //DbFactory is null
        }
    }

    public List<Todo> GetByIds(long[] ids)
    {
        return Db.Ids<Todo>(ids);
    }

    public void Dispose() {
        if (db != null)
            db.Dispose();
    }
}

but when I run this the DbFactory is always null. What's the best way to approach this?

Thank you, Stephen


Solution

  • Three items needed to be coordinated:

    1) Change the signature of the factory, it's important to set the DialectProvider before using the OrmLiteConnectionFactory parameterless constructor.

    OrmLiteConfig.DialectProvider = PostgreSQLDialectProvider.Instance;
    
    var dbFactory = new OrmLiteConnectionFactory();
    
    dbFactory.RegisterConnection("NamedKeyConnOne", 
                             new OrmLiteConnectionFactory(Config.TenantOne));
    dbFactory.RegisterConnection("NamedKeyConnTwo", 
                             new OrmLiteConnectionFactory(Config.TenantTwo));
    

    2) Register the factory

    container.Register<IDbConnectionFactory>(dbFactory);
    

    3) Use the OpenDbConnection method and pass in the "NamedKey", this will return the correct connection.

    public abstract partial class BorrowerRepository : IDisposable
    {
        private IDbConnection _db;
    
        /// <summary>
        /// This should be set to the string - Tenant
        /// </summary>
        public string TenantKey { get; set; }
    
        public IDbConnectionFactory DbFactory { get; set; }
    
        public IDbConnection Db
        {
            get
            {
                if (String.IsNullOrEmpty(TenantKey))
                {
                    throw new ArgumentException("The TenantKey property has to be set before using the DbFactory.");
                }
                return _db ?? (_db = DbFactory.OpenDbConnection(TenantKey));
            }
        }
    
        public virtual void Dispose()
        {
            if (_db == null)
                return;
            _db.Dispose();
        }
    }