简体   繁体   English

在switch语句中为LINQ创建where条件

[英]Creating where condition for LINQ within switch statement

So basically I have to get 4 different List of employees for 4 different roles. 因此,基本上,我必须获得4个不同角色的4个不同的员工列表。 List of Roles is a List of Enum as below: List of Roles是一个List of Enum如下所示:

public enum Roles {
       [Description("Level 1")]
       L1,

       [Description("Level 2")]
       L2,

       [Description("Level 3")]
       L3,

       [Description("Level 4")]
       L4
};
  • L1 can view L1 , L2 , L3 and L4 L1可以查看L1L2L3L4
  • L2 can view L2 , L3 and L4 L2可以查看L2L3L4
  • L3 can view L3 and L4 . L3可以查看L3L4
  • L4 do not have permission to view any of employee. L4没有查看任何员工的权限。

Now below is how I have written query for fetching employees. 现在下面是我如何编写查询以获取员工的信息。

if (!Equals(Role, Enum.GetName(typeof(GlobalMethods.Roles), 3)))
{
      var _role = (GlobalMethods.Roles)Enum.Parse(typeof(GlobalMethods.Roles), Role,true);
      List<EmployeeViewModel> employees = new List<EmployeeViewModel>();
      switch (_role)
      {
            case GlobalMethods.Roles.L1:
                 employees = context.tblEmployees.Where(x => x.EmpID != homeViewModel.UserViewModel.EmpID).ToList().Select(x => new EmployeeViewModel
                 {
                      EmpActive = x.EmpActive,
                      EmpDOB = x.EmpDOB,
                      EmpName = x.EmpName
                 }).ToList();
                 break;
            case GlobalMethods.Roles.L2:
                 employees= context.tblEmployees.Where(x => x.EmpID != homeViewModel.UserViewModel.EmpID).ToList().Where(x=>x.EmpRole != Enum.GetName(typeof(GlobalMethods.Roles), 0)).Select(x => new EmployeeViewModel
                 {
                      EmpActive = x.EmpActive,
                      EmpDOB = x.EmpDOB,
                      EmpName = x.EmpName,
                 }).ToList();
                 break;
            case GlobalMethods.Roles.L3:
                 employees = context.tblEmployees.Where(x => x.EmpID != homeViewModel.UserViewModel.EmpID).ToList().Where(x.EmpRole != Enum.GetName(typeof(GlobalMethods.Roles), 0) && x.EmpRole != Enum.GetName(typeof(GlobalMethods.Roles), 1)).Select(x => new EmployeeViewModel
                 {
                      EmpActive = x.EmpActive,
                      EmpDOB = x.EmpDOB,
                      EmpName = x.EmpName,
                 }).ToList();
                 break;
            default: break;
      }
}

So in the above code I have the same LINQ query but only the where condition differs. 因此,在上面的代码中,我具有相同的LINQ查询,但是只有where条件不同。 Is there any way I can prepare a dynamic where condition and fetch the list once for all? 有什么方法可以准备动态where条件并一次获取列表?

This should work. 这应该工作。 It makes the assumption that each GlobalMethods.Roles can view all roles with a greater int values. 它假设每个GlobalMethods.Roles可以查看具有更大int值的所有角色。 That is the case for the roles are rules that you have stated. 您所指定的角色就是这种情况。

if (!Equals(Role, Enum.GetName(typeof(GlobalMethods.Roles), 3)))
{
     var _role = (GlobalMethods.Roles)Enum.Parse(typeof(GlobalMethods.Roles), Role, true);
     List<EmployeeViewModel> employees = new List<EmployeeViewModel>();
     string[] viewableRoles = GetViewableRoles(_role);
     employees = context.tblEmployees
                .Where(x => x.EmpID != homeViewModel.UserViewModel.EmpID && viewableRoles.Contains(x.EmpRole))
                .Select(x => new EmployeeViewModel
                {
                    EmpActive = x.EmpActive,
                    EmpDOB = x.EmpDOB,
                    EmpName = x.EmpName
                }).ToList();
}

private string[] GetViewableRoles(GlobalMethods.Roles userRole)
{
    //Uncomment if L4 can actually view no roles, including itself.
    // /if (userRole == GlobalMethods.Roles.L4)
    // {
    //  return new string[0];
    // }

    IEnumerable<GlobalMethods.Roles> allRoles = Enum.GetValues(typeof(GlobalMethods.Roles)).Cast<GlobalMethods.Roles>();
    return (from role in allRoles 
                where (int)role >= (int)userRole 
                select role.ToString()).ToArray();
}

This is simplified but you can do something like this: 这是简化的,但是您可以执行以下操作:

class Program
{
    static void Main(string[] args)
    {
        var list = new List<Person>
        {
            new Person{ Name = "John" },
            new Person{ Name = "Amy" }
        };

        Func<Person, bool> pred = null;
        Roles role = Roles.RoleA;
        switch (role)
        {
            case Roles.RoleA:
                pred = p => p.Name.StartsWith("J");
                break;
            case Roles.RoleB:
                pred = p => p.Name.StartsWith("A") && p.Name.Length >= 3;
                break;
            default:
                break;
        }

        var result = list.Where(pred);
    }
}

class Person
{
    public string Name { get; set; }
}

enum Roles
{
    RoleA,
    RoleB
}

Following is the generic Expression tree extension method, to take care of the following requirement (you certainly need to modify to suit your specific requirements) 以下是通用的表达式树扩展方法,可以满足以下要求(您当然需要进行修改以适合您的特定要求)

  • T is the final type of IEnumerable TIEnumerable的最终类型
  • T1 is the type of column for the filtering in the where clause T1是where子句中用于过滤的列的类型

  • Declare ParameterExpression for a given Type T outside extension method for reuse, while compiling Expression Tree to Func , though this can also be done separately in the Extension method and during Func generation 在将Expression Tree to Func编译Expression Tree to Func同时,声明给定Type T外部扩展方法的ParameterExpression以便重用,尽管这也可以在Extension methodFunc生成期间分别完成

    ParameterExpression parameterType = Expression.Parameter(typeof(T), "object");

     public static class CustomExpression { // Create Initial Expression Tree public static BinaryExpression InitialExpression<T,T1>( ParameterExpression parameterType string columnName, T1 value) { // Optional can be taken outside the Extension method to create a Func<T,bool> //ParameterExpression parameterType = Expression.Parameter(typeof(T), "object"); MemberExpression typeColumn = Expression.Property(parameterType, columnName); ConstantExpression constant = Expression.Constant(value, typeof(T1)); return Expression.NotEqual(typeColumn, constant); } // Create Combined Expression Tree public static BinaryExpression CombinedExpression<T,T1>(this BinaryExpression mainExpression, ParameterExpression parameterType string columnName, T1 value) { // Optional can be taken outside the Extension method to create a Func<T,bool> //ParameterExpression parameterType = Expression.Parameter(typeof(T), "object"); MemberExpression typeColumn = Expression.Property(parameterType, columnName); ConstantExpression constant = Expression.Constant(value, typeof(T1)); return Expression.And(mainExpression,Expression.NotEqual(typeColumn, constant)); } } 

Following is the Call Hierarchy in your case: 以下是您的情况下的呼叫层次结构:

  • Declare final binary expression for the Linq query: Linq查询声明最终的二进制表达式:

    BinaryExpression finalBinaryExpression = null;

      switch (_role) { case GlobalMethods.Roles.L1: finalBinaryExpression = CustomExpression.InitialExpression<EmployeeViewModel,int> (parameterType,"EmpID",homeViewModel.UserViewModel.EmpID); break; case GlobalMethods.Roles.L2: finalBinaryExpression = CustomExpression.InitialExpression<EmployeeViewModel,int> (parameterType,"EmpID",homeViewModel.UserViewModel.EmpID) .CombinedExpression<EmployeeViewModel,Roles> (parameterType,"EmpRole",Enum.GetName(typeof(GlobalMethods.Roles), 0)); break; case GlobalMethods.Roles.L3: finalBinaryExpression = CustomExpression.InitialExpression<EmployeeViewModel,int> (parameterType,"EmpID",homeViewModel.UserViewModel.EmpID) .CombinedExpression<EmployeeViewModel,Roles> (parameterType,"EmpRole",Enum.GetName(typeof(GlobalMethods.Roles), 0)) .CombinedExpression<EmployeeViewModel,Roles> (parameterType,"EmpRole",Enum.GetName(typeof(GlobalMethods.Roles), 1)); break; } 
  • Create a genericFunc by compiling the binary expression as follows 通过如下编译二进制表达式来创建一个genericFunc

     Func<T, bool> filterFunc = Expression.Lambda<Func<T, bool>> (finalBinaryExpression, parameterType).Compile(); 
  • Final Result Apply the Func created above 最终结果应用上面创建的Func

      var finalResult = context.tblEmployees.Where(o => filterFunc(o)); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM