Entity framework 6 使用 DI 的动态连接字符串

Entity framework 6 dynamic connections string using DI

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

因此,我将拥有一个具有 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
    ...
}

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

您应该防止将对象注入到基于运行时信息而改变的对象图中。这里的问题是连接字符串是否仍然是一个常量值(在应用程序启动后不会改变),或者可以随着请求的不同而改变(例如,当每个用户获得自己的连接字符串时)。

如果连接字符串是常量,解决方案很简单:只需在 start-up 处请求连接字符串并无限期地使用它,就像您目前已经在做的那样。

如果您的连接字符串不是来自配置文件的常量值,而是运行时信息,则不应再将其及其消耗 DbContext 直接注入到对象图中。相反,您应该定义一个抽象,允许根据运行时信息(例如登录用户)请求正确的 DbContext

所以不是注入一个IContextSomeRepositoryUnitOfWork,而是注入一个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 定义一个实现,它可以从数据库加载正确的连接字符串,并根据该连接字符串创建和缓存 DbContext。考虑到所提供的信息量有限,这只是您会知道如何做的事情。