【问题标题】:Concatenating three lists into one with LINQ throws an exception使用 LINQ 将三个列表连接为一个会引发异常
【发布时间】:2013-07-18 21:50:42
【问题描述】:

好的,我一定是在做一些愚蠢的事情,但这不应该吗?我有以下三个列表:

var commonViews = (from v in context.TPM_VIEWS where v.VIEWID < 0 select v); // IQueryable<TPM_VIEWS>
var ownedViews = (from v in context.TPM_VIEWS where v.OWNERID == userId && v.VIEWID > 0 select v); // IQueryable<TPM_VIEWS>
var sharedViews = (from v in context.TPM_USER.Include("TPM_VIEWS2") where v.USERID == userId select v).First().TPM_VIEWS2; // EntityCollection<TPM_VIEWS>

每个列表都有正确的值和计数。我可以返回以下列表中的任何一个:

return commonViews.ToList();

我可以返回这些列表中的任意一个两个

return commonViews.Concat(ownedViews).ToList();

但是,当我尝试返回所有三个时:

return commonViews.Concat(ownedViews).Concat(sharedViews).ToList();

我得到了例外:

无法创建“Entity.TPM_VIEWS”类型的常量值。仅有的 在此上下文中支持原始类型或枚举类型。

我做错了什么?这三个值确实是可枚举的。大多数情况下,我问这个问题是因为这是保证我会在发布 30 秒后注意到问题的最佳方式。

更新:

我 93% 确定问题出在此处:

var sharedViews = (from v in context.TPM_USER.Include("TPM_VIEWS2") where v.USERID == userId select v).First().TPM_VIEWS2;

这个看起来类似于TPM_VIEWS 对象的可枚举列表,我可以在上面调用ToList() 并获取正确的数据,但它与其他列表不能很好地配合。

更新 2:

这确实有效。指点能告诉我原因的人!

commonViews.ToList().Concat(ownedViews.ToList()).Concat(sharedViews.ToList()).ToList();

【问题讨论】:

  • 试着把sharedViews放在第一位。是的;我严重怀疑这会解决它。
  • 根据我在 EF 的基本历史,我愿意打赌 @SLaks 是对的。
  • 好吧,这很奇怪。 sharedViews.Concat(commonViews).Concat(ownedViews).Count() 返回 6(这是正确的),但 sharedViews.Concat(commonViews).Concat(ownedViews).ToList(); 抛出相同的异常。 sharedViews 肯定很时髦。基本上,我需要从给定的userId 中得到一个IEnumerable&lt;TPM_VIEWS&gt;
  • @JerKimball - 在 SLaks 上投入 5 美元通常是一个安全的赌注,但我认为还有一些其他的事情正在发生。
  • 人们可能会尝试使用.AsEnumerable() 而不是.ToList(),这将强制使用简单的 LINQ 运算符,而不是生成大型 EF IQueryable。应该与.ToList() 具有相同的效果,但在内存使用方面要高效得多。

标签: c# .net linq entity-framework


【解决方案1】:

问题在于 EF IQueryable&lt;T&gt; 上的 Concat() 会将整个串联转换为单个查询。

当您调用 .Concat(sharedViews) 时,您将传递嵌套实体类的标量(预加载)集合。
EF 不知道如何将其转换为查询,因此它会抱怨。

您可以通过调用AsEnumerable() 而不是ToList() 来加快速度。

【讨论】:

  • 太好了,我认为这很好地总结了一切!
  • 那么@MikeChristensen 是否得到 5 美元?
【解决方案2】:

这确实有效。指点能告诉我原因的人!

commonViews.ToList().Concat(ownedViews.ToList()).Concat(sharedViews.ToList()).ToList();

这是因为每个原始查询都是单独执行的;您只是将结果连接到内存中。当您合并 3 个查询时,实体框架查询翻译器中似乎存在一个错误,但是当您在每个查询上调用 ToList 时,它们不再是 EF 查询,它们只是列表,所以它们被连接起来使用 Linq to Objects。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    • 2016-12-20
    • 2014-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多