如何在C#中用switch case或存储过程按条件过滤数据集?
问题描述
我正在处理一项任务,需在请求中传入Status作为参数,根据该Status以及数据库表中未随请求传入的Key列过滤数据。具体规则如下:
- 当Status为
Incomplete且数据库中Key值为null时,获取符合条件的记录(标记为awaiting) - 当Status为
Incomplete且数据库中Key值不为null时,获取符合条件的记录(标记为pending review) - 当Status为
Suspended时,获取符合条件的记录(标记为rejected) - 当Status为
Succeeded时,获取符合条件的记录(标记为approved) - 当Status为
Failed时,获取符合条件的记录(标记为Failed)
我编写了如下C#代码,但存在问题,现咨询是否可不使用switch case语句,改用stored procedure实现该需求?
public class StatusRequest { public Status Status { get; set; } } public Task<StatusSearchResponse> Handle(StatusRequest request) { var projects = Repository.GetProjects(request.Status); switch (request.Status) { case Status.Incomplete && projects.Any(x => x.Key == null): projects.Where(x => x.Status == Status.Incomplete && x.Key == null); break; case Status.Suspended: break; case Status.Succeeded: break; case Status.Failed: break; default: throw new ArgumentOutOfRangeException(); } var response = new StatusSearchResponse(); response.Projects = projects; return SystemTask.FromResult(response); }
解答
现有代码的问题
- C#的
switch不支持在case中写逻辑表达式(Status.Incomplete && projects.Any(...)属于非法写法),case只能匹配常量值。 Where方法是惰性求值且返回新集合,你直接调用但未赋值回projects,导致过滤逻辑完全不生效。- 除了
Incomplete分支,其他分支没有任何实际过滤逻辑,等于未处理。
存储过程实现的可行性
完全可以用存储过程实现该需求,而且把过滤和标记逻辑放到数据库层,能减少不必要的数据传输,提升查询性能,尤其适合数据量较大的场景。
存储过程示例(SQL Server)
假设你的项目表名为Projects,Status字段对应枚举的字符串类型(如果是整数类型,调整参数类型即可),Key为可空列:
CREATE PROCEDURE GetProjectsByStatus @Status NVARCHAR(50) AS BEGIN SET NOCOUNT ON; SELECT *, -- 根据规则生成状态标记 CASE WHEN @Status = 'Incomplete' AND [Key] IS NULL THEN 'awaiting' WHEN @Status = 'Incomplete' AND [Key] IS NOT NULL THEN 'pending review' WHEN @Status = 'Suspended' THEN 'rejected' WHEN @Status = 'Succeeded' THEN 'approved' WHEN @Status = 'Failed' THEN 'Failed' END AS StatusTag FROM Projects WHERE Status = @Status; END GO
C#调用存储过程示例
public Task<StatusSearchResponse> Handle(StatusRequest request) { // 假设Repository提供调用存储过程的方法,传入参数并返回强类型集合 var projects = Repository.FetchFromStoredProcedure<Project>("GetProjectsByStatus", new SqlParameter("@Status", request.Status.ToString())); var response = new StatusSearchResponse { Projects = projects.ToList() }; return Task.FromResult(response); }
额外建议:不用switch和存储过程的替代方案
如果不想用存储过程,也可以用C# 8.0+的模式匹配替代switch,代码更简洁:
public Task<StatusSearchResponse> Handle(StatusRequest request) { var projects = Repository.GetProjects() .Where(p => p.Status == request.Status) .Select(p => new { Project = p, Tag = p.Status switch { Status.Incomplete when p.Key == null => "awaiting", Status.Incomplete when p.Key != null => "pending review", Status.Suspended => "rejected", Status.Succeeded => "approved", Status.Failed => "Failed", _ => throw new ArgumentOutOfRangeException(nameof(request.Status)) } }) .ToList(); var response = new StatusSearchResponse { Projects = projects.Select(x => x.Project).ToList() // 如果需要返回标记,可在此处添加对应字段 }; return Task.FromResult(response); }
内容的提问来源于stack exchange,提问作者Neha Gauda
相关产品推荐
相关产品推荐

