C# 将带有 Case 语句的 SQL 查询转换为 LINQ
Posted
技术标签:
【中文标题】C# 将带有 Case 语句的 SQL 查询转换为 LINQ【英文标题】:C# Convert SQL query with Case statement to LINQ 【发布时间】:2021-07-17 17:34:02 【问题描述】:我在其中一个表中添加了一个新列,该列的结果取决于其他 2 个列的结果。我进行了更新,以便可以用信息填充现有行,但我还想将 case 语句转换为我的代码的 LINQ 查询。
UPDATE depotProjet.Projets
SET IdPlateformeSecteur =
CASE
WHEN (IdPlateforme = 1 AND IdSecteur = 1) then 1
WHEN (IdPlateforme = 1 AND IdSecteur = 2) then 2
WHEN (IdPlateforme = 1 AND IdSecteur = 4) then 3
WHEN (IdPlateforme = 3 AND IdSecteur = 1) then 4
WHEN (IdPlateforme = 3 AND IdSecteur = 2) then 5
WHEN (IdPlateforme = 3 AND IdSecteur = 4) then 6
WHEN (IdPlateforme = 2 AND IdSecteur = 1) then 7
WHEN (IdPlateforme = 2 AND IdSecteur = 2) then 8
WHEN (IdPlateforme = 2 AND IdSecteur = 4) then 9
End
WHERE IdPlateformeSecteur is NULL;
这就是我想出的:
if (projet.IdPlateforme == 1 && projet.IdSecteur == 1)
projet.IdPlateformeSecteur = 1;
else if (projet.IdPlateforme == 1 && projet.IdSecteur == 2)
projet.IdPlateformeSecteur = 2;
else if (projet.IdPlateforme == 1 && projet.IdSecteur == 4)
projet.IdPlateformeSecteur = 3;
else if (projet.IdPlateforme == 3 && projet.IdSecteur == 1)
projet.IdPlateformeSecteur = 4;
else if (projet.IdPlateforme == 3 && projet.IdSecteur == 2)
projet.IdPlateformeSecteur = 5;
else if (projet.IdPlateforme == 3 && projet.IdSecteur == 4)
projet.IdPlateformeSecteur = 6;
else if (projet.IdPlateforme == 2 && projet.IdSecteur == 1)
projet.IdPlateformeSecteur = 7;
else if (projet.IdPlateforme == 2 && projet.IdSecteur == 2)
projet.IdPlateformeSecteur = 8;
else if (projet.IdPlateforme == 2 && projet.IdSecteur == 4)
projet.IdPlateformeSecteur = 9;
我的搜索给了我选择的例子,但我没有选择。它正在工作,但我想以正确的方式做到这一点。谢谢
【问题讨论】:
到目前为止,您发布的只是一堆 If 语句。没有什么关于它的LINQ。您尝试过使用 LINQ 做什么? LINQ 也主要用于选择数据,而不是更新数据,所以你确定你说的是你真正想要的吗?跨度> 我知道我这样做的目的绝不是、塑造或形成 LINQ。我想知道在使用 LINQ 时是否有更雄辩的方式来做我所做的事情?对不起,如果我不清楚。 不是没有看到 if 语句周围的相关代码来获取数据并“更新”它。 对不起,英语不是我的母语,我不确定我理解正确。你还在寻找什么其他代码? 【参考方案1】:我根据您的 depotProjet.Projet
模型和以下类做了一些假设,但应该足够接近以完成您想要的:
(工作 DotNet Fiddle 的链接:https://dotnetfiddle.net/i2RAx3)
您可以使用Func<int, int, int>
传入IdPlatforme
和IdSecteur
将if
语句移出查询(以下使用递归模式匹配并且需要C# 8.0 或更高版本,否则您可以替换它与case
声明):
Func<int, int, int> SetIdPlatformeSecteur = (p, s) =>
int r = (p, s) switch
_ when p == 1 && s == 1 => 1,
_ when p == 1 && s == 2 => 2,
_ when p == 1 && s == 4 => 3,
_ when p == 3 && s == 1 => 4,
_ when p == 3 && s == 2 => 5,
_ when p == 3 && s == 4 => 6,
_ when p == 2 && s == 1 => 7,
_ when p == 2 && s == 2 => 8,
_ when p == 2 && s == 4 => 9,
_ => throw new ArgumentException(message: "Id combination not recognized", paramName: $"p s")
;
return r;
;
然后您可以查询您的项目数据库并返回一个匿名类型,其中包括您添加的项目模型中的字段IdPlateformeSecteur
,如下所示:
new
x.Id,
x.IdPlateforme,
x.IdSecteur,
//...any other properties your model has and want returned
IdPlateformeSecteur = SetIdPlatformeSecteur(x.IdPlateforme, x.IdSecteur)
);
下面的完整 LINQPad 示例:
// Demo data to represent what would be in your databaseContext.Projects
List<Project> Projects =
new List<Project>
new Project Id = 1, IdPlateforme = 1, IdSecteur = 1,
new Project Id = 2, IdPlateforme = 1, IdSecteur = 2,
new Project Id = 3, IdPlateforme = 1, IdSecteur = 4,
new Project Id = 4, IdPlateforme = 3, IdSecteur = 1,
new Project Id = 5, IdPlateforme = 3, IdSecteur = 2,
new Project Id = 6, IdPlateforme = 3, IdSecteur = 4,
new Project Id = 7, IdPlateforme = 2, IdSecteur = 1,
new Project Id = 8, IdPlateforme = 2, IdSecteur = 2,
new Project Id = 9, IdPlateforme = 2, IdSecteur = 4,
;
void Main()
var results = Projects.Select(x => new x.Id, x.IdPlateforme, x.IdSecteur, IdPlateformeSecteur = SetIdPlatformeSecteur(x.IdPlateforme, x.IdSecteur));
results.Dump();
Func<int, int, int> SetIdPlatformeSecteur = (p, s) =>
int r = (p, s) switch
_ when p == 1 && s == 1 => 1,
_ when p == 1 && s == 2 => 2,
_ when p == 1 && s == 4 => 3,
_ when p == 3 && s == 1 => 4,
_ when p == 3 && s == 2 => 5,
_ when p == 3 && s == 4 => 6,
_ when p == 2 && s == 1 => 7,
_ when p == 2 && s == 2 => 8,
_ when p == 2 && s == 4 => 9,
_ => throw new ArgumentException(message: "Id combination not recognized", paramName: $"p s")
;
return r;
;
public class Project
public int Id get; set;
public int IdPlateforme get; set;
public int IdSecteur get; set;
【讨论】:
【参考方案2】:正如@gun2171 表示这里没有关于LINQ
的内容。
为了清楚起见,您当前的代码似乎很容易阅读和维护。如果使用 C# 8,您可以使用 switch 表达式。思考eloquent
,不如想想在几天、几个月或几年后回到代码,你和其他人是否理解这段代码?
Mocked class
public class ProjectItem
public int IdPlateforme get; set;
public int IdSecteur get; set;
public int IdPlateformeSecteur get; set;
Method
在名为 Operations.cs 的类中
private static int SetIdSecteur(ProjectItem sender) => sender.IdPlateforme switch
1 when sender.IdSecteur == 1 => 1,
1 when sender.IdSecteur == 2 => 2,
1 when sender.IdSecteur == 4 => 3,
3 when sender.IdSecteur == 1 => 4,
3 when sender.IdSecteur == 2 => 5,
3 when sender.IdSecteur == 4 => 6,
2 when sender.IdSecteur == 1 => 7,
2 when sender.IdSecteur == 2 => 8,
2 when sender.IdSecteur == 4 => 9,
_ => sender.IdPlateformeSecteur
;
用法
var projet = new ProjectItem() IdPlateforme = 1, IdPlateformeSecteur = 2;
projet.IdSecteur = SetIdSecteur(projet);
编辑
碰巧与 Visual Studio 团队的一位 Microsoft PM 聊天,他们通过使用 C# 8 的元组提供了另一个想法。我对此不以为然,但提出这个替代解决方案似乎是谨慎的。
public static int SetIdSecteur3(ProjectItem sender)
=> (sender.IdPlateforme, sender.IdSecteur) switch
(1, 1) => 1,
(1, 2) => 2,
(1, 4) => 3,
(3, 1) => 4,
(3, 2) => 5,
(3, 4) => 6,
(2, 1) => 7,
(2, 2) => 8,
(2, 4) => 9,
_ => sender.IdPlateformeSecteur
;
【讨论】:
以上是关于C# 将带有 Case 语句的 SQL 查询转换为 LINQ的主要内容,如果未能解决你的问题,请参考以下文章
如何将带有内连接语句的 Sql 查询转换为带有 Where 语句的 sql 查询(语句中没有内连接)