【问题标题】:Entity Framework .Where nested in .Include实体框架 .Where 嵌套在 .Include
【发布时间】:2013-09-13 14:24:36
【问题描述】:

我正在尝试使用 EF5 代码优先执行数据库查找。基本结构和表关系如下;

public partial class Member
{
    public int    RecordID {get; set;}
    public string Name     {get; set;}
    ...etc.
    public virtual ICollection<MemberLink> MasterLinks {get; set;}
    public virtual ICollection<MemberLink> SlaveLinks {get; set;}
    public virtual ICollection<Message>    ReceivedMessages {get; set;}
    public virtual ICollection<Message>    SentMessages {get; set;}
}

public partial class MemberLink
{
    public int            RecordID     {get; set;}
    public virtual Member MasterMember {get; set;}
    public virtual Member SlaveMember  {get; set;}
    ...etc.
}

public partial class Message
{
    public int            RecordID  {get; set;}
    public virtual Member Sender    {get; set;}
    public virtual Member Recipient {get; set;}
    ...etc.
}

现在,我尝试执行的查询正在使用 MemberLinkRepository,看起来像;

public IList<MemberLink> GetMasterLinks(int p_MemberID)
{
    return Get()
           .Include ( memberLink => memberLink.MasterMember )
           .Include ( memberLink => memberLink.SlaveMember )
           .Include ( memberLink => memberLink.MasterMember.ReceivedMessages
                      .Where(
                      msg => msg.Sender.RecordID == memberLink.SlaveMember.RecordID) )
           .Where ( memberLink => memberLink.MasterMember.RecordID == p_MemberID)
           .ToList();

除了 EF 似乎不喜欢嵌套的 Where。我可以将其拆分为 2 个单独的存储库调用(实际上,看起来我可能必须这样做),但为了减少对数据库的调用,我试图一口气完成它。有谁知道我如何在一个查询中实现这一目标?

我希望代码说明了我正在尝试做的事情......如果没有,我会尝试解释得更好。

【问题讨论】:

    标签: entity-framework linq-to-entities ef-code-first repository-pattern


    【解决方案1】:

    简短的回答是否定的,EF 不会让你使用 Include() 这样做。

    考虑一下结果是否允许您这样做:在一种情况下,您的MemberLink.MasterMember.ReceivedMessages 将被完全填充,而在另​​一个外观相同的对象上MemberLink.MasterMember.ReceivedMessages 实际上是消息的子集!如果您尝试添加到 ReceivedMessages 会发生什么?如果添加与过滤器不匹配怎么办?这是一袋伤害。

    答案是使用投影:

    public IList<MemberLinkWithFiltereredMessages> GetMasterLinks(int p_MemberID)
    {
        return Get()
            .Include(memberLink => memberLink.MasterMember)
            .Include(memberLink => memberLink.SlaveMember)
            .Where(memberLink => memberLink.MasterMember.RecordID == p_MemberID)
            .Select(memberLink => new MemberLinkWithFilteredMessages
            {
                MemberLink = memberLink,
                FilteredMessages = memberLink.MasterMember.ReceivedMessages
                    .Where(msg => msg.Sender.RecordID == memberLink.SlaveMember.RecordID)
            })
            .ToList();
    }
    

    您实际上是在询问特定的信息子集,因此请明确说明。

    【讨论】:

    • 太棒了!正是我想要的。同意;您关于明确要求过滤子集的观点是一种更好的方法,因此我将遵循该逻辑:)
    • @user1861826 如果回答了你的问题,请记得打勾:)
    • @TimothyWalters,我有同样的问题。在我的情况下,嵌套深入到多层,我设法做了一个你指出的包含。在生成的 SQL 中,我可以看到所有列都以不同的别名返回,如 c1、c2 之类的。我的问题是,我如何从我的所有包含中形成一个嵌套的 DTO 集合:(.. 可能你可以自己拿上面的例子,因为我们正在返回所有没有任何自定义 DTO 的列(它本身就是 DTO 的集合)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多