0

我在我的應用程序中以DDD方式開發了一個漂亮的乾淨域圖層。開發域時根本沒有考慮數據庫。屬性名稱是有意義的,並非全部大寫,並且與我的應用程序相關。返回不同類型的存儲庫和EF數據上下文有什麼好的模式?

今天,我實現一個存儲庫從現有的EF的DbContext拉。 DbContext被開發爲(基本上)匹配設計不佳的Oracle數據庫。

理想情況下,我想實現這樣一個庫:

public interface IRepository { 
    IQueryable<T> Find<T>(Expression<Func<T, bool>> query) where T : IMyDomainEntity; 
} 

T是我的域實體。但是,我在我的倉庫Find方法裏面,我一定要......

  1. 不知怎的轉換用的DbContext

    工作我不知道如何做到這一點還沒有表達。

  2. 查詢中的DbContext

    一旦表達 '映射',這是簡單的

  3. 不知怎的,映射到我的域對象

    我敢肯定我可以使用AutoMapper或實現我自己的映射器。

  4. 返回一個尚未訪問過數據庫的IQueryable。

    不知道這是可能的畢竟是在干涉#的做1 - 3

那麼,如何有這個問題在過去是解決了嗎?這裏有可重複使用的模式嗎?

+0

溝EF和使用NHibernate的或RavenDb。 (OMG ..是否有人只是建議?! WIN!) –

+1

我和你在一起,但公司不是。我能做的最接近的事情就是與公司溝通。 –

回答

0

嗯,你是在正確的軌道上已有,只需要實現你說什麼,你想:)

1.You're傳遞一個表達式到您的查找方法,只需使用在表達你在哪裏第

2.You只需從你的DbContext對查詢得到正確的DbSet,擁有的DbContext的方法來獲得給定類型的的DbContext,使用並可以查詢像

public IQueryable<T> Find<T>(Expression<Func<T, bool>> query) where T : IMyDomainEntity 
{ 
    var dbSet = context.Set<T>(); 
    return dbSet.Where(query); 
} 

3 。如果你的域對象是不是EF映射到數據庫中的,你需要定製針對什麼在你的數據庫在你的DbContext類(無需automapper爲)你的映射,所以你會有這樣的事情你的DbContext類

public class MyContext : DbContext 
{ 
    ... 
     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      modelBuilder.Entity<User>() 
       .Map(a => a.ToTable("DB_USERS")) 
       .Property(a => a.Email).HasColumnName("MAIL"); 

      base.OnModelCreating(modelBuilder); 
     } 
} 

要在DB到類用戶表DB_USERS地圖,具有領域不同的名字,等這裏的一對是

http://www.codeproject.com/Articles/165720/Using-the-Code-First-Model-Configuration-Classes

您也可以映射的文章如果您不想/不能更改您的DbCon,則使用屬性將屬性添加到正確的表列文本類

http://msdn.microsoft.com/en-us/data/gg193958

或者你可以有一組不同的映射到你的數據庫,並使用automapper將其轉化爲你的域對象的實體,但你不失時機。因爲您需要實現查詢以將其自動映射到您的域模型。

4.No需要做什麼特別的事情,EF照顧的是

UPDATE:解決方案,而無需到的DbContext(不完全仿製藥,但作品)

的想法是訪問爲每個域類創建存儲庫的映射部分,這樣所有的都可以正確綁定。與User域模型和DBUser表格模型在繼續:

public class User : IDomainModelEntity 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Email { get; set; } 
} 

public class DBUser 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int USER_ID { get; set; } 

    [Required] 
    [MaxLength(150)] 
    public string USER_NAME { get; set; } 

    [Required] 
    [MaxLength(260)] 
    public string USER_MAIL { get; set; } 
} 

那麼你將有一個抽象庫,每個域類的一個具體的存儲庫實現映射的基本GETALL查詢:

public abstract class Repository<T> where T : IDomainModelEntity 
{ 
    protected readonly DbContext _context; 

    public Repository(DbContext context) 
    { 
     _context = context; 
    } 

    public abstract IQueryable<T> GetAll(); 

    public IQueryable<T> Find(Expression<Func<T, bool>> predicate) 
    { 
     return GetAll().Where(predicate); 
    } 

} 

public class UserRepository : Repository<User> 
{ 
    public UserRepository(DbContext context) 
     : base(context) 
    { 
    } 

    public override IQueryable<User> GetAll() 
    { 
     return _context.Set<DBUser>() 
      .Select(u => new User 
       { 
        Id = u.USER_ID, 
        Name = u.USER_NAME, 
        Email = u.USER_MAIL 
       }); 
    } 
} 

現在使用它,你將只需要調用查找或讓所有的倉庫......

 using (var context = new CompanyDbContext()) 
     { 
      var repo = new UserRepository(context); 
      var list = repo.Find(a=>a.Id >= 2).ToList(); 

      list.ForEach(a => Console.WriteLine("Id: {0}, Name {1}, email {2}", a.Id, a.Name, a.Email)); 
     } 

這不是因爲喲完全通用ü將需要傳遞一個信息庫,你需要使用的每個域類,但它可能是一個可以接受的妥協

希望這有助於

+0

context.Set 不存在,因爲T是IMydomainEvent和我的域名事件不會在的DbContext存在。我的域實體和EF實體是不同的對象類型。 –

+0

看到我編輯的第3號映射 – Jaime

+0

我已經交給了現有的EF DbContext。我無法改變它。我必須照原樣處理它。 –

相關問題