【问题标题】:CastleWindsor, Generic Repository and two database contextsCastleWindsor、通用存储库和两个数据库上下文
【发布时间】:2015-01-05 12:59:37
【问题描述】:

我有两个独立的数据库用于存储文档和用户。我还实现了通用存储库模式:

 public class Repository<T> : IRepository<T> where T : class
    {
        public DbContext Context { get; set; }

        public Repository()
        {

        }

        public IEnumerable<T> Get(Expression<Func<T, bool>> expression)
        {
            return Context.Set<T>().Where(expression).AsEnumerable();
        }

        public void Add(T entity)
        {
            Context.Set<T>().Add(entity);
        }

        public void Delete(T entity)
        {
            Context.Set<T>().Remove(entity);
        }

        public void Update(T entity)
        {
            Context.Set<T>().Attach(entity);
            Context.Entry<T>(entity).State = EntityState.Modified;
        }


        public void SaveChanges()
        {
            Context.SaveChanges();
        }
    }

问题是实体存储在不同的 DbContexts 中,我不能使用这样的东西:

container.Register(Component.For(typeof(IRepository<>)).ImplementedBy(typeof(Repository<>));

如何指定每个实体应使用哪个 DbContext?
例如,如果我想创建存储库,这意味着应该使用一个数据库,但如果我想存储库,则应该使用另一个上下文。 或者我应该创建两个 repo 类,如下所示:

public class AttachmetRepository<T> : IRepository<T> where T : class
    {
        public AttachmetsDbContext Context { get; set; }
        ...
    }

    public class UserRepository<T> : IRepository<T> where T : class
    {
        public UsersDbContext Context { get; set; }
        ...
    }

我不想使用两个不同的存储库的原因是为了保持服务简单,如下所示:

 public class SomeService: ISomeService
    {
        public IRepository<User> UserRepository { get; set; } //database 1
        public IRepository<Comment> CommentsRepository { get; set; } //database 1
        public IRepository<Attachment> AttachmentRepository { get; set; } //database 2
        ...
}

统一更新: 正如 Ognyan 建议的那样,我使用了 FactoryMethod,这很有帮助!非常感谢,奥格尼安! 我是 CastleWindsor 的新手,我不确定这是最好和最快的方法,但这是我的代码:

public class EFDatabaseInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Component.For<AttContext>().LifeStyle.PerWebRequest);
            container.Register(Component.For<DefContext>().LifeStyle.PerWebRequest);

            container.Register(Component.For(typeof(IRepository<>)).UsingFactoryMethod((kernel, context) =>
            {
                var genericType = context.RequestedType.GetGenericArguments()[0];

                Type type = typeof(Repository<>).MakeGenericType(genericType);
                object repository = Activator.CreateInstance(type);
                PropertyInfo dbContextProperty = type.GetProperty("Context");

                if (genericType == typeof(Attachment))
                {
                    dbContextProperty.SetValue(repository, kernel.Resolve<AttContext>());
                }
                else
                {
                    dbContextProperty.SetValue(repository, kernel.Resolve<DefContext>());
                }

                return repository;
            }).LifeStyle.PerWebRequest);
        }
    }

【问题讨论】:

    标签: c# entity-framework castle-windsor


    【解决方案1】:

    首先,您不需要在存储库中对 DbContext 进行硬编码。您可以像这样重新制作您的存储库:

    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly DbContext _dbContext;
        // you can even make it IDbContextProvider with .Current() method in order not
        // to place a hard dependency but depend on Interface which is the proper way.
        // I was in a hurry and did not want to overcomplicate the implementation.
    
        public Repository(DbContext dbContext)
        {
            _dbContext = dbContext;
        }
    
        protected IDbSet<T> CreateSet<T>() where T : class
        {
            return _dbContext.Set<T>(); 
        }
    
        public virtual T Find(int id)
        {
            return CreateSet<T>().Find(id);
        }
    ... 
    }
    

    之后,您需要一个工厂方法和一种区分目标数据库的方法。一种区分方法是从工厂方法的 CreationContext 中获取信息:

    private static DbContext DbContextFactoryMethod(IKernel k, ComponentModel cm, CreationContext c)
    

    您可以在此处遍历解析堆栈,查看这是否是包含 IRepository 或其他实体的图形的一部分,然后选择您的数据库。

    通过这种方式,您将在存储库中获得正确的 DbContext,而无需将它们全部粘贴在其中,这会随着时间的推移变得越来越麻烦。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多