为SingleOrDefault Linq方法定义默认值

6

我试图从Entity Framework中获取数据记录ID:

var plantAreaID = await db.PlantAreas
  .Where(p => p.Plant.CompanyNo == companyNo && p.Plant.Abbreviation == companyAbbr)
  .Select(p => p.ID)
  .SingleOrDefaultAsync();

问题在于,存在一个ID为0的PlantArea。但是,如果未找到任何记录,则SingleOrDefault会返回0。那么我该如何区分ID 0和未找到数据的情况?
我的第一个想法是提供默认值-1,但在这种情况下,SingleOrDefault似乎不支持这样做。
我该怎么办?
2个回答

8

null 是表示缺失值的常规方式。

var plantAreaID = await db.PlantAreas
   .Where(p => p.Plant.CompanyNo == companyNo && p.Plant.Abbreviation == companyAbbr)
   .Select(p => new int?(p.ID))
   .SingleOrDefaultAsync();

如果您想使用-1来表示缺失值,您可以说:
var plantAreaID = await db.PlantAreas
   .Where(p => p.Plant.CompanyNo == companyNo && p.Plant.Abbreviation == companyAbbr)
   .Select(p => new int?(p.ID))
   .SingleOrDefaultAsync() ?? -1;

感谢您的想法。我发现了 DefaultIfEmpty(-1) 方法,并跟随一个简单的 SingleAsync()。您更倾向于哪个呢? - André Reichelt
1
如果您想使用自定义默认值,那么DefaultIfEmpty可能更好。 如果您只想要null,我认为我更喜欢我的方式,但这只是我的思维方式罢了 :) - gnud
1
无论如何,这始终只会是0或1行,因此对性能没有影响。 - gnud
3
null 是指示缺失值的正常方式。” 这就是答案。成本为单一可空转换,即零成本。 DefaultIfEmpty 和通常的魔数是更差的选择。请注意,即使对于非可空表达式,返回 NULL 在 SQL 中也是自然的——需要转换只是为了让 C# 编译器满意。 - Ivan Stoev
1
“SingleOrDefault()”只有在使用EF(Linq to SQL)时才能被翻译,这并不是EF团队为此目的而做出的设计决策。如果序列中没有单个元素(这就是名称所暗示的),则IEnumerable接口中的“SingleOrDefault()”应该返回默认的T。 - DevilSuichiro
显示剩余3条评论

3

我找到了另一个解决方案,不需要转换:

int plantAreaID = await db.PlantAreas
  .Where(p => p.Plant.CompanyNo == companyNo && p.Plant.Abbreviation == companyAbbr)
  .Select(p => p.ID)
  .DefaultIfEmpty(-1)
  .SingleAsync();

DefaultIfEmpty被应用在查询端,所以并不比cast更好,正如其他人所说的,“null”是表示无数据的更清晰的方式。 - AFract
@AFract 是的。但是 nullable 类型也会在客户端引入一些(不必要的)额外开销,是吗? - André Reichelt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接