0

我有一個存儲庫模式,我正在使用的應用程序。今天一切都很完美。但是,我想增加將關係包含到其他模型的功能。如何使用c#將關係添加到我的存儲庫模式?

這是我目前的IRepository

public interface IRepository<TModel> 
    where TModel : class 
{ 

    // Get records by it's primary key 
    TModel Get(int id); 

    // Get all records 
    IEnumerable<TModel> GetAll(); 

    // Get all records matching a lambda expression 
    IEnumerable<TModel> Find(Expression<Func<TModel, bool>> predicate); 

    // Get the a single matching record or null 
    TModel SingleOrDefault(Expression<Func<TModel, bool>> predicate); 

    // Add single record 
    TModel Add(TModel entity); 

    // Add multiple records 
    IEnumerable<TModel> AddRange(IEnumerable<TModel> entities); 

    // Remove records 
    void Remove(TModel entity); 

    // remove multiple records 
    void RemoveRange(IEnumerable<TModel> entities); 
} 

這裏是我的實體實施

public class EntityRepository<TEntity> : IRepository<TEntity> 
where TEntity : class 
{ 
protected readonly DbContext Context; 

protected readonly DbSet<TEntity> DbSet; 

public EntityRepository(DbContext context) 
{ 
    Context = context; 
    DbSet = context.Set<TEntity>(); 
} 

public TEntity Get(int id) 
{ 
    return DbSet.Find(id); 
} 

public IEnumerable<TEntity> GetAll() 
{ 
    return DbSet.ToList(); 
} 

public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate) 
{ 
    return DbSet.Where(predicate); 
} 

public TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate) 
{ 
    return DbSet.SingleOrDefault(predicate); 
} 

public TEntity Add(TEntity entity) 
{ 
    TEntity record = DbSet.Add(entity); 

    return record; 
} 

public IEnumerable<TEntity> AddRange(IEnumerable<TEntity> entities) 
{ 
    IEnumerable<TEntity> records = DbSet.AddRange(entities); 

    return records; 
} 

public void Remove(TEntity entity) 
{ 
    DbSet.Remove(entity); 
} 

public void RemoveRange(IEnumerable<TEntity> entities) 
{ 
    DbSet.RemoveRange(entities); 
} 

現在,我想補充的另一種方法,讓我來處理延遲加載。 換句話說,我希望能夠做這樣的事

using(var con = new UnitOfWork()) 
{ 
    var task = con.Tasks.With(x => x.Owner).GetAll(); 
} 

在這裏,在我的工作類

public sealed class UnitOfWork : IUnitOfWork 
{ 
    private bool Disposed = false; 
    private readonly ModuleContext Context; 

    public ITaskRepository Tasks { get; private set; } 

    public UnitOfWork(ModuleContext context) 
    { 
     Context = context; 
     Tasks = new TaskRepository(Context); 
    } 

    public int Save() 
    { 
     return Context.SaveChanges(); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
    } 

    private void Dispose(bool disposing) 
    { 
     if (!Disposed && Context != null && disposing) 
     { 
      Context.Dispose(); 
     } 

     Disposed = true; 
    } 
} 

這裏的單位是我的任務模型

public class Task 
{ 
    public string Name { get; set; } 

    [ForeignKey("Client")] 
    public int ClientId { get; set; } 

    [ForeignKey("Owner")] 
    public int? OwnerId { get; set; } 

    public virtual Client Client { get; set; } 
    public virtual User Owner { get; set; } 
} 

哪有我添加了一種方法讓我可以將關係包含到不同的模型中?

+0

轉儲工作存儲庫/工作單元。請參閱:https://cpratt.co/repository-and-unit-of-work-patterns-with-entity-framework/。 TL; DR:實體框架*已經*實現了這些模式。你的'DbContext'是你的工作單元,每個'DbSet'都是一個倉庫。你所做的只是增加另一個無意義的抽象,這需要額外的維護。 –

+1

儘管DbContext已經實現了這些,但我們並不知道OP的意圖。這可能是因爲他們想要完全抽象出EF,因此DAL稍後可以基於其他技術(可能是EF核心)。在這種情況下,如果DbContext已經實現了這些模式,這並沒有什麼不同。另外,如果你有一個存儲庫/工作單元層,模擬你的DAL可以更容易進行單元測試。根據我的經驗,嘲笑DbContext有點複雜。 –

+1

如果我以後不想使用EF會怎麼樣?而且......如果我按照你的建議轉儲模式。我會在哪裏保存我的可重用代碼?如果我有一個where子句,我在哪裏使用,我將在哪裏保存,所以我有一個地方爲我所有的邏輯 –

回答

0

爲您的方法添加一個重載到存儲庫接口以接受可能的包含表達式列表。例如。

public IEnumerable<TEntity> FindAll(params Expression<Func<TEntity,object>> includes) 
{ 
    var query = DbSet; 
    foreach (var include in includes) 
    { 
     query = query.Include(include); 
    } 
    return query.ToList(); 
} 

然後你就可以這樣寫:

uow.Tasks.GetAll(t=>t.Owner); 

因爲你可以做這樣的事情的過濾情況:

public IEnumerable<TEntity> Find(Expression<Func<TEntity,bool>> filter, params Expression<Func<TEntity,object>> includes) 
{ 
    var query = DbSet; 
    foreach (var include in includes) 
    { 
     query = query.Include(include); 
    } 
    return query.Where(filter).ToList(); 
} 

然後你就可以這樣寫:

uow.Tasks.Find(t=>t.Something==2, t=>t.Owner); 
+0

謝謝。如果我想過濾然後包含關係呢? .where()。include()... –

+0

查看我更新的過濾案例。 –

+0

感謝您的更新。但是,返回'IQueryable ''有什麼問題? –

相關問題