代码之家  ›  专栏  ›  技术社区  ›  Wheels

使用DI的实体框架6动态连接字符串

  •  1
  • Wheels  · 技术社区  · 7 年前

    我有一个使用存储库模式的工作单元,实现了简单的注入器,我需要动态更改连接字符串。当前,连接字符串取自web配置。我需要从数据库中获取连接字符串。

    所以我将有一个数据库与ASP。Net标识和连接字符串(以及应用程序所需的其他配置),然后是数据库,具体取决于客户端。

    我的存储库和工作单元如下所示。

    public abstract class DataRepositoryBase<TEntity, TContext> : IDataRepository<TEntity>
        where TEntity : class, IObjectStateEntity, new()
        where TContext : class, IDbSimpleContextAsync
        {
            protected DataRepositoryBase(TContext context)
            {
                Context = context;            
            }
    
            public virtual TContext Context { get; }
    
            public IEnumerable<TEntity> Get()
            {
                return Context.Get<TEntity>();
            }
    
            public TEntity Get(object id)
            {
                return Context.Find<TEntity>(id);
            }
    }
    
    public class SomeRepository : DataRepositoryBase<SomeObject, IContext>, ISomeRepository
    {
        public SomeRepository (IContext context) : base(context)
        {
        }
    }
    
    public abstract class UnitOfWorkBase : IUnitOfWork
    {
        private IDbSimpleContextAsync _dbContext;
    
        protected UnitOfWorkBase(IDbSimpleContextAsync dbContext)
        {
            _dbContext = dbContext;
        }
    
        public int SaveChanges()
        {
            return _dbContext.SaveChanges();
        }
    
        public Task<int> SaveChangesAsync()
        {
            return _dbContext.SaveChangesAsync();
        }
    }
    
    public class UnitOfWork : UnitOfWorkBase, IUnitOfWork
    {
        private ISomeRepository _someRepository
        private readonly IContext _dbContext;
    
        public UnitOfWork(IContext dbContext) : base(dbContext)
        {
            _dbContext = dbContext;
        }
    
        public ISomeRepository SomeRepository => _someRepository ?? (_someRepository = new SomeRepository(_dbContext));
    }
    
    public class BookingBusiness : IBookingBusiness
    {
        protected IAllotmentUnitOfWork UnitOfWork { get; }
    
        public AllotmentBusinessBase(IUnitOfWork unitOfWork)
        {
            UnitOfWork = unitOfWork;
        }
    
        ...
        business methods here
        ...
    }
    

    因此,我的想法是,在接触业务时,我在配置数据库中查询当前用户的连接字符串(注入到该数据库的当前工作单元),并以某种方式使用该连接实例化新的工作单元,以便连接到正确的数据库。有什么想法可以用我目前的设置来实现这一点吗?

    1 回复  |  直到 7 年前
        1
  •  0
  •   Steven    7 年前

    应防止向对象图中注入根据运行时信息更改的对象。这里的问题是连接字符串是否仍然是一个常量(在应用程序启动后不会更改),或者是否可以在不同的请求之间更改(例如,当每个用户都获得自己的连接字符串时)。

    如果连接字符串是常量,解决方案很简单:只需在启动时请求连接字符串并无限期地使用它,就像您当前正在做的那样。

    如果您的连接字符串不是配置文件中的常量值,而是运行时信息,那么它及其使用 DbContext 不应再直接注入到对象图中。相反,您应该定义一个抽象,允许请求正确的 数据库上下文 基于运行时信息,如登录用户。

    因此,与其注射 IContext 进入 SomeRepository UnitOfWork ,注入 IContextProvider ,定义如下:

    public interface IContextProvider
    {
        IContext Context { get; }
    }
    

    你的 DataRepositoryBase 可以使用 IContextProvider 具体如下:

    public IEnumerable<TEntity> Get()
    {
        return this.contextProvider.Context.Get<TEntity>();
    }
    
    public TEntity Get(object id)
    {
        return this.contextProvider.Context.Find<TEntity>(id);
    }
    

    剩下的部分是定义 IContextProvider 可以从数据库中加载正确的连接字符串,并创建和缓存 数据库上下文 基于该连接字符串。考虑到所提供的信息量有限,这只是您将知道如何做的事情。

    推荐文章