Linq转换SQL查询时非聚合字段返回类型而非数据的问题
解决Linq查询中非聚合字段返回类型信息而非实际值的问题
你遇到的核心问题是:Code和Isin字段没有返回预期的字符串值,而是输出了集合的类型信息。这是因为你对Distinct()返回的集合直接调用了ToString(),而这个方法默认会返回对象的类型名称,不是集合里的元素值。
问题根源分析
在你的Linq代码里:
Code = g.Select(i => i.tts.Number).Distinct().ToString(), Isin = g.Select(i => i.ts.Isin).Distinct().ToString(),
g.Select(...)返回的是一个IEnumerable<string>集合,哪怕Distinct()之后只剩一个元素,直接调用ToString()也只会输出类似System.Linq.Enumerable+DistinctIterator的类型标识,而不是你要的字段值。
另外注意:你的SQL查询中取的是trans_series.number,但Linq里写的是i.tts.Number,这可能是字段映射错误,应该改为i.ts.Number(对应trans_series的number字段)。
修复后的代码
因为你是按tts.SeriesId分组,而ts.Id和tts.SeriesId是关联的,每个分组内的trans_series相关字段(number、isin)必然是唯一的,所以直接取分组内第一个元素的对应值即可,甚至不需要Distinct():
public List<TotalByIsinViewModel> GetIssuerSeries() { _context = new MySQLDatabaseContext(); var result = (from ts in _context.TradesSeries join tts in _context.TradesTrades on ts.Id equals tts.SeriesId where myInClause.Contains(tts.SeriesId) && tts.FirstPartyId == null && tts.Status != "closed" && tts.Status != "cancelled" group new { ts, tts } by new { tts.SeriesId } into g select new TotalByIsinViewModel { SeriesId = g.Key.SeriesId, // 取分组内唯一的trans_series.number值 Code = g.Select(i => i.ts.Number).SingleOrDefault(), // 取分组内唯一的trans_series.isin值 Isin = g.Select(i => i.ts.Isin).SingleOrDefault(), Amount = (decimal?)g.Sum(pt => pt.tts.Amount), NumberOfTrades = g.Count() }).ToList(); return result; }
关键说明
SingleOrDefault()vsFirstOrDefault():- 如果能确保每个分组内必然存在对应字段值,用
SingleOrDefault()更严谨(如果分组内出现多个不同值会抛出异常,帮你发现数据问题); - 如果允许字段值为空,用
FirstOrDefault()更安全。
- 如果能确保每个分组内必然存在对应字段值,用
- 字段映射校验:确认
ts.Number确实对应SQL里的trans_series.number,避免因字段混淆导致数据错误。
内容的提问来源于stack exchange,提问作者Intrepid2020
相关产品推荐
相关产品推荐

