2015-01-05 26 views
1

我有兩個單獨的數據庫用於存儲文檔和用戶。此外,我已經實現了通用倉庫模式:CastleWindsor,通用存儲庫和兩個數據庫上下文

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應用於每個實體?
例如,如果我想創建Repository,這意味着應該使用一個數據庫,但是如果我需要Repository,則應該使用另一個上下文。 或者我應該創建兩個回購類,像這樣:

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 
     ... 
} 

UPD: 由於Ognyan建議我使用了FactoryMethod,這有助於!非常感謝Ognyan! 我是新來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); 
     } 
    } 

回答

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,而不會將所有內容都粘在裏面,隨着時間變得越來越繁瑣。

相關問題