LINQ Linq2Sql可查询SelectMany InvalidOperationException

时间:2017-03-15 09:15:11

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

// 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));

编辑:

使用LinqPad 4和SQL Connection Linq2SQL测试 Net Framework 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()

1 个答案:

答案 0 :(得分: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()

编辑:Pr评论这不能解决问题;但是它会删除一个间接层,并且可以更容易地解决问题。

问题是,三级表达式隐藏了类型,使提供者只能使用一个可枚举的类型。一个潜在的解决方案是避免高等教育。

 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)