实体框架延迟加载与通用存储库 [英] Entity Framework Lazy Loading with generic repository

本文介绍了实体框架延迟加载与通用存储库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我当前的项目使用通用库接口,这样的:

My current project uses a generic repository interface, thus:

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();
}

作为一个例子,在获取方法是这样的:

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

其中,分贝是一个实例我的数据上下文,扩展实体框架的的DbContext 。整个事情农具的IDisposable ,这样我可以在一个范围内的块使用它的单元的工作模式,提交更改,或处置,如果整个事情之前等待结束一些之前出现问题。

where db is an instance my data context, which extends Entity Framework's DbContext. The whole thing implements IDisposable so that I can use it in a scope block for unit-of-work pattern, waiting to the end before committing changes, or disposing the entire thing if something goes wrong before that.

此接口由一个逻辑层来处理更复杂的查询,以保持从数据访问完全分开的业务逻辑。因此,查询到该层可能是这样的:

This interface is used by a logic layer to handle more complex queries, to keep business logic entirely separated from data access. So, a query to that layer might go like this:

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));
    }
}

(是的,我认识到,可以浓缩;它是在应用程序,但对于一个例子,这是更清晰)

我的问题是,有时我回一组对象,再后来,我可能想要得到它的一些引用的东西。例如,当我得到一个产品展示,显示可能要做到这一点:

My problem is that sometimes I return a set of objects, and then later I might want to get to some of the things it references. For example, when I get a Product to display, the Display might want to do this:

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

(忽略HTML的质量;再次,它是一个简单的例子)

问题是,当实体框架的延迟加载叶从我的查询返回的实体时,这些属性空,这会引发错误。现在,我知道了包括()方法,但如果我的仓库是通用的则是难以适用的。我可以把它完全关闭,但随后将EF开始检索的东西联系在一起的巨大集合时,我不需要他们 - 我的模型的结构,事情已经出到审计日志的链接意味着很多的EF链接随之而来。

The problem is that this throws errors when Entity Framework's lazy loading leaves these properties null when returning entities from my queries. Now, I'm aware of the Include() method, but if my repository is generic then it's difficult to apply those. I could turn it off entirely, but then EF will start retrieving enormous linked collections of things when I don't need them - the structure of my model and the links that things have out to the audit logs mean a lot of links for EF to follow.

有没有办法,我可以延迟加载在一个稍微更聪明的方式?有没有像一个方法。单()。凡()我可以在<$ C $调用C> DbSet ,将带给孩子对象为好,这样我可以专门要求子对象包含了一定的查询?

Is there a way that I can lazy-load in a slightly smarter manner? Is there a method like .Single() and .Where() that I can call on the DbSet that will bring child objects as well, so that I can specifically ask for child objects to be included for a certain query?

推荐答案

添加一个可选参数包含路径然后调用包含(STR)。与Get方法示例:

add an optional parameter for the include path then invoke Include(str) on the DbSet. Example with your Get method:

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);
}

这篇关于实体框架延迟加载与通用存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆