我在LINQPad中运行此查询。它的工作原理除了ProductSeries有重复的记录。
var query = from etaRecord in EtaRecord_0140
join productSeriesRecord in ProductSeries
on etaRecord.ProductSeriesID equals productSeriesRecord.ProductSeriesID
into productSeriesGroup
from productSeries in productSeriesGroup.DefaultIfEmpty()
where etaRecord.State == "A"
select new { EtaRecord = etaRecord, ProductSeriesRecord = productSeries };
query.Dump();
我尝试使用FirstOrDefault()
代替DefaultIfEmpty()
,但我收到此错误:
类型为' LINQPad.User.ProductSeries'的表达式是不允许的 具有源类型的查询表达式中的后续from子句 ' System.Linq.IQueryable&#39 ;.类型推断失败了 拨打' SelectMany'。
如何获取ProductSeries的FirstOrDefault()
,以便每个EtaRecord只有一行?
.NET小提琴就在这里:https://dotnetfiddle.net/kRrold
答案 0 :(得分:1)
看起来你需要分组:
var query = from etaRecord in EtaRecord_0140
join productSeriesRecord in ProductSeries
on etaRecord.ProductSeriesID equals productSeriesRecord.ProductSeriesID
into productSeriesGroup
from productSeries in productSeriesGroup.DefaultIfEmpty()
where etaRecord.State == "A"
group productSeries by new { etaRecord.ProductSeriesId, etaRecord } into g
select new
{
EtaRecord = g.Key.etaRecord,
ProductSeriesRecord = g.Select(x => x).FirstOrDefault()
};
答案 1 :(得分:0)
您是说您加入的收藏品有重复吗?因为如果是这样,您可以提前对ProductSeries集合进行分组。
var query = from etaRecord in EtaRecord_0140
join productSeriesRecord in ProductSeries.GroupBy(series => series.ProductSeriesID).Select(seriesGroup => seriesGroup.First())
on etaRecord.ProductSeriesID equals productSeriesRecord.ProductSeriesID
into productSeriesGroup
from productSeries in productSeriesGroup.DefaultIfEmpty()
where etaRecord.State == "A"
select new { EtaRecord = etaRecord, ProductSeriesRecord = etaRecord };
query.Dump();
现在假设您正在使用静态列表,而不是数据库。如果它是数据库连接,那么您应该对结果执行不同的操作。事后可以以类似的方式完成。
答案 2 :(得分:0)
我会在子查询中执行此操作:
var query = from etaRecord in EtaRecord_0140
where etaRecord.State == "A"
select new
{
EtaRecord = etaRecord,
ProductSeriesRecord =
(from productSeriesRecord in ProductSeries
where productSeriesRecord.ProductSeriesID == etaRecord.ProductSeriesID
select productSeriesRecord).FirstOrDefault()
};
在LINQ to对象中,这可能是一个低效的操作,因为子查询是为每个etaRecord
执行的,但由于整个语句被转换为SQL,查询优化器将处理优化的执行计划。
这是LINQ-to-entities的故事。
LINQ-to-SQL 总是似乎为组连接(join - into
)和FirstOrDefault()
生成n + 1个查询。我尝试了几种方案,但我无法生成一个查询。我能找到生成一个查询的唯一解决方案是:
var query = from etaRecord in EtaRecord_0140
where etaRecord.State == "A"
from productSeriesRecord in
ProductSeries
.Where(ps => ps.ProductSeriesID == etaRecord.ProductSeriesID)
.Take(1)
.DefaultIfEmpt()
select new { EtaRecord = etaRecord, ProductSeriesRecord = productSeries };
因此,放弃了连接语法,并以相当人为的方式查询属于ProductSeries
的{{1}}的第一条记录。
答案 3 :(得分:0)
问题是您的额外from
条款:
from productSeries in productSeriesGroup.DefaultIfEmpty()
你应该放弃,只需使用:
let productSeries = productSeriesGroup.FirstOrDefault()
...或者只在productSeriesGroup.FirstOrDefault()
子句中使用select
,如下所示:
var query = from etaRecord in etaRecords
join productSeriesRecord in productSeriesRecords
on etaRecord.ProductSeriesId equals productSeriesRecord.ProductSeriesId
into productSeriesGroup
select new { EtaRecord = etaRecord,
ProductSeriesRecord = productSeriesGroup.FirstOrDefault() };
如果有任何改变,结果现在是:
Snuh 1 - null
Snuh 2 - null
Snuh 3 - null
Snuh 4 - Description A
Snuh 5 - null
Snuh 6 - Description B
我认为这就是你想要的。
答案 4 :(得分:0)
你应该可以添加一个额外的过滤步骤来按EtaRecord分组,只需选择每组的第一条记录
即
query = (from r in query
group r by r.EtaRecord.EtaId into results
select results.FirstOrDefault());