1

我正在将存储库模式与 EF 一起使用,我认为我对此非常满意,但仍然存在一个问题;

如果我想急切加载实体,最好的方法是什么?

例如,我有一个映射到实体的存储库:

public class EFFooRepository : IFooRepository
{
     public IQueryable<Foo> GetFoo()
     {
        .....
     }
}

如果我想获取 Foo 和 Bar 对象怎么办

db.Foo.Include("Bar")

但是我的存储库只返回 Foo,所以我需要创建另一个方法 GetFooAndBar 吗?

有没有更好的办法?

4

2 回答 2

1

我也有同样的经历。当我实现存储库模式时,我希望能够使用 DbSet<T> 实现的 IQueryable<T> 和 IEnumerable<T>,而不暴露 DbSet<T>(旧信息隐藏)

因此我认为让所有的 IQueryable / IEnumerable 函数调用 Repository 中 DbSet<T> 的相应函数就足够了。

直到今天,这对于我所有的 IQueryable<T> 函数来说已经足够了。今天我发现除了 IQueryable.Include 有你描述的同样的问题。没有编译器错误,但没有加载数据。

经过广泛的结果,我发现原因在QueryableExtensions.Include Method (IQueryable, String)的 MSDN 描述中有所描述

此扩展方法调用源 IQueryable 对象的 Include(String) 方法(如果存在此类方法)。如果源 IQueryable 没有匹配方法,则此方法不执行任何操作。

所以我所要做的就是在我的存储库中编写一个匹配的包含语句,该语句将调用相应的 DbSet 存储库。IQueryable / IEnumerable 函数只是调用 DbSet 的相应函数:

public class Repository<T> : 
    System.Linq.IQueryable<T>, System.Collections.Generic.IEnumerable<T>,
    System.Linq.IQueryable, System.Collections.IEnumerable
    where T : class, new()
{
    public Repository(DbContext dbContext)
    {
        this.dbContext = dbContext;
        this.dbSet = dbContext.Set<T>();
    }

    public readonly DbSet<T> dbSet;
    private readonly DbContext dbContext;

    public virtual DbQuery<T> Include(string path)
    {
        return this.dbSet.Include(path);
    }

    // other Repository functions: Find / Add / Update / Remove etc

为了完整性,IQueryable / IEnumerable 实现:

    #region IQueryable
    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return ((IQueryable<T>)this.dbSet).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable)this.dbSet).GetEnumerator();
    }

    Type IQueryable.ElementType
    {
        get { return ((IQueryable<T>)this.dbSet).ElementType; }
    }

    System.Linq.Expressions.Expression IQueryable.Expression
    {
        get { return ((IQueryable)this.dbSet).Expression; }
    }

    IQueryProvider IQueryable.Provider
    {
        get { return ((IQueryable)this.dbSet).Provider; }
    }
    #endregion IQueryable

现在以下工作,地址包括:

using (MyDbContext dbContext = new MyDbContext(...))
{
    Repository<Customer> customers = new Repository<Customer>(dbContext);
    var happyCustomers = customers
        .Include(customer => customer.Address)
        .Where(customer => customer.IsHappy);
    Show(happyCustomers);
}
于 2016-03-09T16:02:58.367 回答
0

如果您启用了延迟加载,则可以加载Bar后者(当您要访问该属性时)。但是,如果您想编写一个同时加载数据的方法,FooBar的,您需要编写特定的存储库方法。

于 2012-05-10T09:07:20.333 回答