SQL CASE语句转C# LINQ扩展方法技术求助
解决LINQ转换SQL CASE语句并获取最后一条记录的问题
你的代码无法得到预期结果,主要有两个核心问题:
- 排序方向错误:你要获取的是「最后一条记录」(也就是最新录入的、Id最大的那条),但原代码用了
OrderBy(s => s.Id)(升序排序),这会返回Id最小的最早记录,和你的需求相反。 - 默认值与返回类型不匹配:SQL里的
ELSE NULL对应可空的数值,但你的代码用了0作为默认值,并且方法返回int类型,既不符合SQL逻辑,还可能导致错误的结果(比如0不是有效的物料ID,会和真实数据混淆)。
下面是修正后的两种写法:
一、扩展方法(方法语法)写法
public int? GetLastShipmentMaterialEntry() { var lastShipmentMaterialEntry = BarcodeReceivingDbContext.Shipments // 严格匹配SQL的s.material <> '',如果Material可能为null,建议加上s.Material != null .Where(s => s.Material != "") // 降序排序,确保拿到Id最大的最后一条记录 .OrderByDescending(s => s.Id) // 用switch表达式替代嵌套三元,更清晰易读(C# 8.0+支持) .Select(s => s.Material switch { "P4861VAPF" => 4578, "P2871VAPF" => 4579, "P2231VAPF" => 4580, _ => null // 对应SQL的ELSE NULL }) .FirstOrDefault(); return lastShipmentMaterialEntry; }
二、查询语法写法
如果你更喜欢LINQ查询语法的可读性,也可以这么写:
public int? GetLastShipmentMaterialEntry() { var query = from shipment in BarcodeReceivingDbContext.Shipments where shipment.Material != "" orderby shipment.Id descending select shipment.Material switch { "P4861VAPF" => 4578, "P2871VAPF" => 4579, "P2231VAPF" => 4580, _ => null }; return query.FirstOrDefault(); }
兼容旧版C#的写法(无switch表达式)
如果你的项目用的是C# 8.0之前的版本,可以把switch表达式换回嵌套三元运算符:
.Select(s => s.Material == "P4861VAPF" ? 4578 : s.Material == "P2871VAPF" ? 4579 : s.Material == "P2231VAPF" ? 4580 : (int?)null)
额外说明
- 如果你需要严格匹配SQL中
s.material <> ''的逻辑(SQL中NULL <> ''会被过滤),请确保Where条件写为Where(s => s.Material != "");如果你的Material字段可能为null,可以改为Where(s => !string.IsNullOrEmpty(s.Material))来同时排除null和空字符串。 - 返回类型改为
int?(可空整数),这样当没有匹配的物料或者没有符合条件的记录时,会返回null,和SQL的行为一致,避免用0造成歧义。
内容的提问来源于stack exchange,提问作者NewCoder
相关产品推荐
相关产品推荐

