3

我一直在使用一种设计模式,在使用 Entity Framework Profiler 之后似乎它可能非常愚蠢。

我已经扩展了我的实体类,使其具有作为与该实体关联的集合的过滤视图的属性。像这样:

public IEnumerable<Member> ActiveMembers
{
    get
    {
        return Members.Where(t => t.LeftDate == null);
    }
}

因为我主要对没有离开俱乐部的会员感兴趣,所以这个属性非常有用并且似乎很有意义。

但是,通过运行 EF Profiler,我现在知道这通常会导致 N+1 问题。如果我遍历成员并且还想显示他们的地址,那么每个地址请求都会导致额外的数据库查询。

我从这个问题知道我问我可以将我的财产修改为:

return Members.CreateSourceQuery().Include("Address")
              .Where(t => t.LeftClubDate == null);

在这种情况下,这将消除 N+1 问题,但我并不总是想要地址信息,我可能想要关注 Member 的另一个导航属性。

理想情况下,我希望能够保持我的过滤属性(如 ActiveMembers)的灵活性,并能够在事后决定要在查询中包含哪些属性。像这样:

var membersToDisplay = ActiveMembers.Include("Address").ToList();

这可能吗,还是我需要重新考虑我的过滤属性想法?

4

1 回答 1

3

不,无法调用Include。是/的特征。可以调用on (使用 EFv4.1 或自定义扩展),但它仍然在内部将传递的查询强制转换为or并在无法完成强制转换时抛出异常。您必须重新设计您的应用程序。IEnumerableIncludeObjectQueryDbQueryIncludeIQueryableObjectQueryDbQuery

我并不总是想要地址信息,我可能想要关注 Member 的另一个导航属性。

您必须根据当前需求填充数据或忍受 N+1 问题。例如,您可以使用单独的 linq 查询:

var clubId = ActiveClub.Id;
var members = (from member in context.Members.Include("Address")
               where member.LeftDate == null and member.ClubId == clubId
               select member).ToList();
于 2011-05-14T13:02:07.800 回答