C# 使用Linq而不使用硬编码的多个复选框选择结果

C# 使用Linq而不使用硬编码的多个复选框选择结果,c#,asp.net-mvc,linq,asp.net-mvc-4,linq-to-entities,C#,Asp.net Mvc,Linq,Asp.net Mvc 4,Linq To Entities,数据库图示(实际列和表名不同) 我有什么问题? 我的应用程序中有一个isChecked、IsRetired和IsHoliday复选框,允许用户选中多项选择并提交 系统将根据用户选择从数据库返回员工列表。例如,当用户勾选IsChecked和IsRetired时,系统将返回患病并从数据库中退休的用户列表 基于下面的代码,我需要写2^3=8个可能性来得到结果。 当该列扩展到n列(不包括employeeID列)时,我需要编写2^n if else语句来获取查询。 如果有10列(选择10个复选框),那么我

数据库图示(实际列和表名不同)

我有什么问题?
我的应用程序中有一个isChecked、IsRetired和IsHoliday复选框,允许用户选中多项选择并提交
系统将根据用户选择从数据库返回员工列表。例如,当用户勾选IsChecked和IsRetired时,系统将返回患病并从数据库中退休的用户列表

基于下面的代码,我需要写2^3=8个可能性来得到结果。 当该列扩展到n列(不包括employeeID列)时,我需要编写2^n if else语句来获取查询。 如果有10列(选择10个复选框),那么我需要写2^10=1024 If-else语句

在我看来,这应该是开发人员面临的一个相当普遍的问题,不幸的是,我无法在网上找到一个很好的解决方案

对解决方案的期望
C#代码和/或LINQ查询的通用组合,不需要硬编码逻辑,如下if(…)else if(…)


您可以使用名为LINQKit的库,并使用其创建带有动态OR的谓词

var employee = db.Employee.AsQueryable():
var predicate = PredicateBuilder.False<Employee>();
if (model.IsSicked == true)
    predicate = predicate.Or(p => p.IsSick == model.IsSick);
if (model.IsRetired == true)
    predicate = predicate.Or(p => p.IsRetired == model.IsRetired);
if (model.IsHoliday == true)
    predicate = predicate.Or(p => p.IsHoliday == model.IsHoliday);
var result = employee.AsExpandable().Where(c => predicate.Invoke(c)).ToList()
var employee=db.employee.AsQueryable():
var predicate=PredicateBuilder.False();
如果(model.IsSicked==true)
谓词=谓词.Or(p=>p.IsSick==model.IsSick);
如果(model.IsRetired==true)
谓词=谓词.Or(p=>p.IsRetired==model.IsRetired);
如果(model.IsHoliday==true)
predicate=predicate.Or(p=>p.IsHoliday==model.IsHoliday);
var result=employee.AsExpandable().Where(c=>predicate.Invoke(c)).ToList()

为什么不将
枚举
[Flags]
一起使用:

[Flags]
public enum EmployeeStatus
{
    None = 0,
    Sick = 1,
    Retired = 2,
    Holiday = 4
}
在数据库中,可以将其存储为整数

您的模型将类似于

public class Employee
{
    public int Id { get; set; }
    public EmployeeStatus Status { get; set }
}
然后LINQ查询变得类似于:

employee.Where(z => z.Status == EmployeeStatus.Sick)
由于使用了
[Flags]
,您可以对多个状态执行以下操作,例如生病和退休:

employee.Where(z => z.Status == (EmpoyeeStatus.Sick | EmployeeStatus.Retired))
请注意,
|
是布尔值或,其翻译如下:

  EmpoyeeStatus.Sick | EmployeeStatus.Retired
= 1 | 2
= b01 | b10
= b11
= 3

因此,在我们的逻辑中有效地起到“and”的作用。

您可以这样构建Where谓词:

var employee = db.Employee.AsQueryable():

if(model.IsSicked == true)
    employee = employee.Where(z => z.IsSicked == true)

if(model.IsRetired == true)
    employee = employee.Where(z => z.IsRetired == true)

if (model.IsHoliday == true)
    employee = employee.Where(z => z.IsHoliday == true)
或者,您可以这样做:

employee.Where(z => (z.IsSicked || !model.IsSicked) &&
                    (z.IsRetired || !model.IsRetired) &&
                    (z.IsHoliday || !model.IsHoliday))

我要试穿一下this@Estagra我已经添加了一个示例,正如我在文章前面提到的,上面的表名和列只是说明,并不代表我正在处理的真正的表。事实上,您提供的解决方案很好,假设员工只能是您上面提到的状态之一。我在这里工作的是一个解决方案,员工可能同时生病和退休,或者同时生病、退休或休假(在这种情况下,这似乎不符合逻辑)@Estagra我已经更新了答案,表明你可以用我的解决方案来做这件事。你提供的第一个答案不是被选中了==true first,然后,只有filter IsRetired==true,如果有多个true,则结果较小;如果有多个true,则结果应该更大或相等,因为它是或
var employee = db.Employee.AsQueryable():

if(model.IsSicked == true)
    employee = employee.Where(z => z.IsSicked == true)

if(model.IsRetired == true)
    employee = employee.Where(z => z.IsRetired == true)

if (model.IsHoliday == true)
    employee = employee.Where(z => z.IsHoliday == true)
employee.Where(z => (z.IsSicked || !model.IsSicked) &&
                    (z.IsRetired || !model.IsRetired) &&
                    (z.IsHoliday || !model.IsHoliday))