【问题标题】:Multiple CheckBox Selection Result using Linq without hardcoding使用 Linq 的多个 CheckBox 选择结果,无需硬编码
【发布时间】:2015-02-16 13:36:27
【问题描述】:

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

EmployeeeID      IsSicked   IsRetired    IsHoliday  
1                false      false        true
2                true       false        true
3                true       true         true
4                false      false        false

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

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

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

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

var employee = db.Employee.AsQueryable():
if(model.IsSicked == true)
{
    employee.Where(z => z.IsSicked == true)
}
else if(model.IsRetired == true)
{
    employee.Where(z => z.IsRetired == true)
}
...
...

else if(model.IsSicked == true && model.IsRetired == true)
{
    employee.Where(z => z.IsSick == true || z.IsRetired == true)
}
else if (model.IsSicked == true && model.IsRetired == true && model.IsHoliday == true)
{
    employee.Where(z => z.IsSick == true || z.IsRetired == true || z.IsHoliday == true)
}

【问题讨论】:

    标签: c# asp.net-mvc linq asp.net-mvc-4 linq-to-entities


    【解决方案1】:

    为什么不使用enum[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))
    

    请注意,| 是布尔值 OR,其转换如下:

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

    在我们的逻辑中如此有效地充当“和”。

    【讨论】:

    • 正如我之前在帖子中提到的,上面的表名和列是说明性的,并不代表我正在处理的真实表。确实,您提供的解决方案很好,假设员工只能是您上面提到的状态之一。我在这里工作的是一个解决方案,其中员工可以同时生病和退休,或者同时生病、退休或休假(在这种情况下这似乎不合逻辑)
    • @Estagra 我已经更新了答案,表明您可以使用我的解决方案做到这一点。
    【解决方案2】:

    您可以使用名为 LINQKit 的库并使用其 PredicateBuilder 来创建具有动态 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()
    

    【讨论】:

    • 会试试这个
    • @Estagra 我添加了一个例子
    【解决方案3】:

    您可以像这样构建您的 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))
    

    【讨论】:

    • 不是您提供的第一个答案 filter isSicked == true 首先,然后只过滤 IsRetired == true 如果有多个 true 会导致较小的结果,如果有则应该更多或相等的结果是多重真,因为它是或
    猜你喜欢
    • 2014-03-06
    • 1970-01-01
    • 2022-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    相关资源
    最近更新 更多