【问题标题】:LINQ Linq2Sql Queryable SelectMany InvalidOperationExceptionLINQ Linq2Sql 可查询 SelectMany InvalidOperationException
【发布时间】:2023-03-11 10:38:02
【问题描述】:
// usual stuff
var medias = Medias.Where(a => !a.Removed);


 // Find the last date in our collection
 var lastDateWithValues = medias.Select(a => a.Date).Distinct().ToList().OrderByDescending(a => a.Date).Select(a => a.Date).FirstOrDefault();

 // Group collection by Property
 var myQuery = (from m in medias
 group m by m.PropertyId into mg
 // filter last 12 month and group by our TypeId
 let lastValues = mg.Where(f => f.Date > lastDateWithValues.AddMonths(-12)).GroupBy(x => x.MediaTypeId)
 // check if this any of this "TypeGroup" has 12 or month values
 let hasTwelve = lastValues.Where(a => a.Count() >= 12)
 // if it has 12 or more values in any of those groups, return values flatten. If not, return empty
 let results = hasTwelve.Any() ? lastValues.SelectMany(x => x) : Enumerable.Empty<Media>().AsQueryable()
 select results);

这很好用,但现在我想用 SelectMany 把它弄平:

 var dontWork = myQuery.SelectMany(x => x);

 var worksFine = myQuery.ToList().AsQueryable().SelectMany(x => x);

有没有我可以重写 myQuery 所以我不需要使用 ToList() 来使它工作?

谢谢,

Edit2:在 taemyr 的帮助下重写:

var lastDateWithValues = medias.Select(a => a.Date).Distinct().ToList().OrderByDescending(a => a.Date).FirstOrDefault();
var mediaDataRange = medias.Where(f => f.Date > lastDateWithValues.AddMonths(-12));
var fullProperties = mediaDataRange.GroupBy(x => new { x.PropertyId, x.MediaTypeId}).Where(x => x.Count() >= 12).Select(x => x.Key.PropertyId).Distinct().ToList();
var result = mediaDataRange.Where(x => fullProperties.Contains(x.PropertyId));

编辑:

这是使用带有 SQL 连接 Linq2SQL 的 LinqPad 4 进行测试的 网络框架 4.6.1

来自 LinqPad 的完整错误消息: 无法格式化节点“ClientQuery”以作为 SQL 执行

vid System.Data.Linq.SqlClient.SqlFormatter.Visitor.VisitClientQuery(SqlClientQuery cq)
vid System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
vid System.Data.Linq.SqlClient.SqlFormatter.Visitor.VisitSearchedCase(SqlSearchedCase c)
vid System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
vid System.Data.Linq.SqlClient.SqlFormatter.Visitor.VisitAlias(SqlAlias alias)
vid System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
vid System.Data.Linq.SqlClient.SqlFormatter.Visitor.VisitJoin(SqlJoin join)
vid System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
vid System.Data.Linq.SqlClient.SqlFormatter.Visitor.VisitSelect(SqlSelect ss)
vid System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node)
vid System.Data.Linq.SqlClient.SqlFormatter.Visitor.Format(SqlNode node, Boolean isDebug)
vid System.Data.Linq.SqlClient.SqlFormatter.Format(SqlNode node)
vid System.Data.Linq.SqlClient.SqlProvider.BuildQuery(ResultShape resultShape, Type resultType, SqlNode node, ReadOnlyCollection parentParameters, SqlNodeAnnotations annotations)
vid System.Data.Linq.SqlClient.SqlProvider.BuildQuery(Expression query, SqlNodeAnnotations annotations)
vid System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
vid System.Data.Linq.DataQuery`1.System.Collections.IEnumerable.GetEnumerator()
vid LINQPad.UI.ExplorerGrid.ConvertToList(IEnumerable source)
vid LINQPad.UI.ExplorerGrid.UpdateDataSourceToUse()

【问题讨论】:

  • 您的dontWork 提出InvalidOperationException?完整的错误文本是什么?
  • 你得到什么错误信息。您希望使用 SelectMany(x=>x) 完成什么?
  • 错误消息:无法格式化节点“ClientQuery”以作为 SQL 执行
  • 完成:由于性能原因,我希望查询保持为 IQueryable
  • 所以这不是一般的 LINQ,而是查询提供程序特定的问题。什么是查询提供程序类型 - 即 EF6、EF Core 等?

标签: c# sql linq linq-to-sql


【解决方案1】:

尽量不要分组。

 // filter last 12 month and group by our TypeId
 let lastValues = mg.Where(f => f.Date > lastDateWithValues.AddMonths(-12))
 let lastValuesGrouped=lastValues.GroupBy(x => x.MediaTypeId)
 // check if this any of this "TypeGroup" has 12 or month values
 let hasTwelve = lastValuesGrouped.Where(a => a.Count() >= 12)
 // if it has 12 or more values in any of those groups, return values flatten. If not, return empty
 let results = hasTwelve.Any() ? lastValues : Enumerable.Empty<Media>().AsQueryable()

编辑:公关评论这不能解决问题;但是,它消除了一层间接性,使问题更容易解决。

问题在于第三个表达式隐藏了类型,使提供者只剩下一个可枚举的对象。一个潜在的解决方案是避免第三级。

 let lastValues = mg.Where(f => f.Date > lastDateWithValues.AddMonths(-12))
 let lastValuesGrouped=lastValues.GroupBy(x => x.MediaTypeId)
 let hasTwelve = lastValuesGrouped.Where(a => a.Count() >= 12).Select(x=>x.Key)
 let results = lastValues.Where(x=>hasTwelve.Contains(x.MediaTypeId)

【讨论】:

  • 不,同样的错误。尝试了很多不同的方法,但同样的错误。
  • @Tom 嗯。好的 - 这让我重现了这个问题。建议得到改进。
  • 好的,谢谢,通过使用包含您建议的重写查询来解决。如果您有兴趣,请查看我的编辑。
  • @Tom 如果我的回答解决了您的问题,请接受回答。
猜你喜欢
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 2021-04-30
  • 2016-05-30
  • 1970-01-01
  • 2011-06-09
  • 2011-06-09
  • 2013-11-24
相关资源
最近更新 更多