UOW + Repository + Autofac加载两个不同的DbContext [英] UOW + Repository + Autofac load two different DbContext

查看:908
本文介绍了UOW + Repository + Autofac加载两个不同的DbContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天遇到了一个问题,我无法解决这个问题,我搜索了很多,无法进入解决方案,请尽可能帮助我。

I'm facing an issue today and I'm unable to solve it, I searched a lot and can't get into a solution, please help me if you can.

我正在实现一个使用EF +存储库模式+使用Autofac工作单元的MVC应用程序作为依赖注入器。

I'm implementing a MVC application which uses EF + Repository Pattern + Unit Of Work with Autofac as the Dependency Injector.

我能够使用一个DbContext类,但我面临的情况是需要使用另一个DbContext实例(其他用户凭据访问另一个数据库)

I was able to work with one DbContext class, but I'm facing a situation where I need to use another DbContext instance (which access another database with another user credentials)

让我解释更好:我有来自数据库A(并具有DatabaseA_Context类)的EntityA。所以我需要一个来自数据库B(具有自己的DatabaseB_Context类)的EntityB。

Let me explain better: I have EntityA which comes from database A (and have a DatabaseA_Context class). So I need a EntityB, which comes from database B (with its own DatabaseB_Context class).

当我使用AutoFac注册时,只有最后配置的依赖关系注入到GenericRepository实现上。

When I register they with AutoFac, only the last configured dependency is injected on the GenericRepository implementation.

I已经发现文章说Autofac覆盖了最后一个值的注册。

I've already found articles saying that Autofac overrides the registration with the last value.

我已经找到其他文章,显示如果我在UnitOfWork构造函数中传递一个IEnumerable,我可以看到所有注册的类型,但我想要一个特定的。

I've already found other article that shows if I pass an IEnumerable on the UnitOfWork constructor, I'm able to see all of the registered types for it, but I want a specific one.

我已经足够清楚了吗?

我的代码如下:

我的控制器:

public class MyController : Controller
{
    private readonly IBaseBLL<EntityA> _aBLL;
    private readonly IBaseBLL<EntityB> _bBll;

    public MyController(IBaseBLL<EntityA> aBLL, IBaseBLL<EntityB> bBLL)
    {
        _aBLL = aBLL;
        _bBLL = bBLL;
    }
}

我的业务层

public interface IBaseBLL<T> where T : class
{
    T Select(Expression<Func<T, bool>> predicate);
    T AddT entity);
    void Update(T entity);
    T Delete(T entity);
}

public class BaseBLL<T> : IBaseBLL<T> where T : class
{
    private readonly IUnitOfWork _uow;

    public BaseBLL(IUnitOfWork uow)
    {
        _uow = uow;
    }

    //implementation goes here...
}

我的UOW实现

public interface IUnitOfWork : IDisposable
{
    int SaveChanges();
    IGenericRepository<T> Repository<T>() where T : class;
}

public class UnitOfWork : IUnitOfWork
{
    private readonly DbContext _dbContext;
    private bool disposed = false;
    private Dictionary<Type, object> repositories;


    public UnitOfWork(DbContext dbContext)
    {
        _dbContext = dbContext;
        repositories = new Dictionary<Type, object>();
    }

    public IGenericReposity<T> Repository<T>() where T : class
    {
        if (repositories.Keys.Contains(typeof(T)))
            return repositories[typeof(T)] as IGenericReposity<T>;

        IGenericReposity<T> repository = new GenericRepository<T>(_dbContext);
        repositories.Add(typeof(T), repository );
        return repository ;
    }

    public int SaveChanges()
    {
        return _dbContext.SaveChanges();
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
            if (disposing)
                _dbContext.Dispose();

        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

我的存储库实现

public class GenericRepository<T> : IGenericRepositoryT> where T : class
{
    protected readonly DbContext _dbContext;
    protected IDbSet<T> _dbSet;

    public GenericRepository(DbContext dbContext)
    {
        _dbContext = dbContext;
        _dbSet = _dbContext.Set<T>();
    }

    //implementation goes here...
}

我的AutoFac注册(在Global.asax文件中)

My AutoFac registration (in Global.asax file)

var builder = new ContainerBuilder();

builder.RegisterType(typeof(DatabaseA_Context)).As(typeof(DbContext)).InstancePerLifetimeScope();
builder.RegisterType(typeof(DatabaseB_Context)).As(typeof(DbContext)).InstancePerLifetimeScope();
builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerRequest(); 

请帮助

推荐答案

您应该使用命名和关键的服务

builder.RegisterType<DatabaseA_Context>()
       .Named<DbContext>("databaseA")
       .InstancePerLifetimeScope();
builder.RegisterType<DatabaseB_Context>()
       .Named<DbContext>("databaseB")
       .InstancePerLifetimeScope();

然后,您可以在注册时指定您想要的组件的DbContext

Then you can specify the DbContext you want for a component at registration

builder.RegisterType<MyService>()
       .As<IService>()
       .WithParameter((pi, c) => pi.Name == "dbContext", 
                      (pi, c) => c.ResolveNamed<DbContext>("databaseA"))

或使用 IIndex<,>

public class MyService : IService
{
    public MyService(IIndex<String, DbContext> dbContexts)
    {
        var databaseA = dbContexts["databaseA"];
    }
}

自动填充还支持指定使用 WithKeyAttribute命名注册

public class MyService : IService
{
    public MyService([WithKey("DatabaseA")DbContext dbContext)
    {
    }
}

请参阅元数据文档有关如何获取 WithKeyAttribute 设置的更多信息。

See the metadata documentation for more info on how to get the WithKeyAttribute set up.

使用此解决方案, DbContext 将不会被注册。如果你想要一个默认的 DbContext ,你可以这样注册:

With this solution, DbContext won't be registered. If you want a default DbContext you can register one like this :

builder.Register(c => c.ResolveNamed<DbContext>("databaseA"))
       .As<DbContext>()
       .InstancePerLifetimeScope(); 

您还可以使用根据参数名称选择正确注册的模块: / p>

You can also use a module that will choose the correct registration based on the name of the argument :

public class MyService : IService
{
    public MyService(DbContext dbContextA, DbContext dbContextB)
    {
    }
}

为了做到这一点,你需要注册这个 Autofac 模块

To do this you will need to register this Autofac Module

public class DbContextModule : Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        registration.Preparing += Registration_Preparing;
    }

    private void Registration_Preparing(Object sender, PreparingEventArgs e)
    {
        Parameter parameter = new ResolvedParameter(
                                (pi, c) => pi.ParameterType == typeof(DbContext),
                                (pi, c) =>
                                {
                                    if (pi.Name.Equals("dbContextA", StringComparison.OrdinalIgnoreCase))
                                    {
                                        return c.ResolveNamed<DbContext>("databaseA");
                                    }
                                    else if (pi.Name.Equals("dbContextB", StringComparison.OrdinalIgnoreCase))
                                    {
                                        return c.ResolveNamed<DbContext>("databaseB");
                                    }
                                    else
                                    {
                                        throw new NotSupportedException($"DbContext not found for '{pi.Name}' parameter name");
                                    }
                                });
        e.Parameters = e.Parameters.Concat(new Parameter[] { parameter });
    }
}

builder.RegisterModule<DbContextModule>()

这篇关于UOW + Repository + Autofac加载两个不同的DbContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆