1

我当前的项目使用通用存储库接口,因此:

public interface IDataSource : IDisposable
{
    void Add<T>(T newItem) where T : EntityBase;

    T Get<T>(Guid id) where T : EntityBase;
    T Get<T>(Expression<Func<T, bool>> predicate) where T : EntityBase;
    IQueryable<T> GetAll<T>(Expression<Func<T, bool>> predicate = null) where T : EntityBase;
    int Count<T>(Expression<Func<T, bool>> predicate = null) where T : EntityBase;
    bool Any<T>(Expression<Func<T, bool>> predicate = null) where T : EntityBase;

    void Update<T>(T updated) where T : EntityBase;

    void Delete<T>(Guid id) where T : EntityBase;
    void Delete<T>(T item) where T : EntityBase;

    void Commit();
}

例如,该Get方法如下所示:

public T Get<T>(Expression<Func<T, bool>> predicate) where T : EntityBase
{
    return db.Set<T>().Single(predicate);
}

我的数据上下文的实例在哪里db,它扩展了实体框架的DbContext. 整个事情的实现IDisposable,以便我可以在工作单元模式的范围块中使用它,在提交更改之前等待结束,或者如果在此之前出现问题,则处理整个事情。

逻辑层使用此接口来处理更复杂的查询,以使业务逻辑与数据访问完全分离。因此,对该层的查询可能如下所示:

public List<Product> ItemsBoughtByCustomer(Guid customerID)
{
    using (var db = DataAccess.GetContext())
    {
        List<Purchase> purchaseHistory = db.GetAll<Purchase>(p => p.CustomerID == customerID);
        List<int> IDs = purchaseHistory.Select(p => p.ProductID);
        return db.GetAll<Product>(p => IDs.Contains(p.ID));
    }
}

(是的,我意识到可以浓缩;它在应用程序中,但例如,这更清楚。)

我的问题是有时我会返回一组对象,然后我可能想要获取它引用的一些东西。例如,当我要显示一个产品时,显示可能想要这样做:

@foreach (Comment comment in Product.Comments)
{
    <div class="comment">
        <span>@Html.UserDisplay(comment.Author)</span>
        <span>@comment.Body</span>
    </div>
}

(忽略 HTML 的质量;同样,这是一个简单的示例)

问题是,当 Entity Framework 的延迟加载在从我的查询返回实体时使这些属性为空时,这会引发错误。现在,我知道该Include()方法,但如果我的存储库是通用的,那么很难应用它们。我可以完全关闭它,但是当我不需要它们时,EF 将开始检索大量链接的事物集合——我的模型的结构和事物与审计日志的链接意味着 EF 有很多链接到跟随。

有没有一种方法可以让我以更智能的方式进行延迟加载?是否有类似的方法.Single().Where()我可以调用该方法DbSet,它也会带来子对象,以便我可以专门要求将子对象包含在某个查询中?

4

1 回答 1

1

为包含路径添加一个可选参数,然后在 DbSet 上调用 Include(str)。您的 Get 方法示例:

public T Get<T>(Expression<Func<T, bool>> predicate, string includePath = null) where T : EntityBase
{
    var query = db.Set<T>();

    if( !string.IsNullorWhitespace( includePath ) )
    {
        query = query.Include( includePath );
    }

    return query.Single(predicate);
}
于 2013-03-27T15:09:26.547 回答