【问题标题】:Include with projection does not work包含投影不起作用
【发布时间】:2011-12-16 13:41:23
【问题描述】:

我有这个问题

    var test = context.Assignments
        .Include(a => a.Customer)
        .Include(a => a.Subscriptions)
        .Select(a => new AssignmentWithSubscriptionCount { SubscriptionCount = a.Subscriptions.Count(), Assignment = a })
        .ToList();

    var name = test.First().Assignment.Customer.Name;

它无法急切地加载客户,我在 stackoverflow 上看到了类似的问题,看起来你不能使用包含的投影。但是我还没有找到解决我的问题的方法。。有人吗?

编辑:这是一个有效的投影负载,它比上面的示例更复杂,所以我无法理解有什么问题,谢谢。

    var test = context.PublicationStateGroups
        .Include(p => p.PublicationStates.Select(ps => ps.AllowedPublicationStateActions.Select(aps => aps.PublicationStateAction)))
        .Select(psg => new StateAndGroupInfo
        {
            ShowReport = psg.PublicationStates.Any(p => p.PublicationStateReportTypeId.HasValue),
            Actions = psg.PublicationStates.SelectMany(state => state.AllowedPublicationStateActions)
                .Select(a => a.PublicationStateAction)
                .Distinct()
        }).ToList();

    var eagerTest = test.First().Actions.First().Name;

【问题讨论】:

  • 第二个示例与您的第一个示例不同。在第二个中,您只能访问 Actions 集合中的一个元素,该元素直接是您的投影对象中的一个成员。首先,您尝试访问投影成员 Assignment 上的导航属性 Assignment.Customer,但这是行不通的。您可以在两个示例中删除 Include,它不会改变任何内容。
  • 啊,那是正确的 :D 所以你告诉我 EF 是一个如此不成熟的产品,我不能这样做并保持映射对象上的关系?我告诉我的团队成员我们应该选择 nHibernate,但他们不想听:/
  • 是的,据我所知,不支持投影中的Include。 MS似乎也证实了这一点(见下面拉迪斯拉夫的回答)。我的回答只是一种解决方法。

标签: include entity-framework-4.1 projection


【解决方案1】:

将客户添加到您的投影中:

var test = context.Assignments
    .Select(a => new AssignmentWithSubscriptionCount
    {
        SubscriptionCount = a.Subscriptions.Count(),
        Assignment = a,
        Customer = a.Customer
    });

var name = test.First().Customer.Name;

EF 上下文可能会确保自动填充Assignment.Customer

编辑

如果您不想或无法更改AssignmentWithSubscriptionCount 类,您也可以投影为匿名类型,然后将内存中的结果复制到该类中:

var test = context.Assignments
    .Select(a => new
    {
        SubscriptionCount = a.Subscriptions.Count(),
        Assignment = a,
        Customer = a.Customer
    });

test.ToList() // executes query
    .Select(o =>
    {
        o.Assignment.Customer = o.Customer;
        return new AssignmentWithSubscriptionCount
        {
            SubscriptionCount = o.SubscriptionCount,
            Assignment = o.Assignment
        }
    });

另一种选择是显式加载(尽管每次加载 Assignment 需要一个额外的往返)。

【讨论】:

  • 一定有比这更好的解决方案吗?
  • @Anders:我有另一个解决方案(请参阅我的编辑),但它更好吗?你不需要用第二种方式改变你的投影类 - 如果这是你不喜欢第一种选择的方式。
  • 不,感觉必须有更好的方法并保持与实际分配类型的关系...我有另一个更高级的投影,它可以工作,所以必须有别的东西,我有工作中的代码无法发布可悲的代码
  • @Anders:第一个代码可能会设置Assignment.Customer。上下文将把它放在一起(因为“关系跨度”)。这就是我在第一个 sn-p 下方的评论的意思。但是,您不能禁用更改跟踪。我很好奇你的工作投影示例。
  • 我用有效的查询更新了我的问题。您的解决方案适用于一级关系,但我与客户有更深层次的关系,我需要并将它们全部放在投影上不是解决方案这行得通......对不起
【解决方案2】:

这是by designInclude 不适用于具有投影或自定义连接的场景。

【讨论】:

  • 但是还有其他方法可以包含子关系而不将它们从映射类型移动到投影?编辑:抱歉错过了您的链接,我会检查一下
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-15
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 2018-12-09
相关资源
最近更新 更多