动态LINQ语句

时间:2015-07-28 17:39:11

标签: c# linq entity-framework .net-4.5

我正在尝试使用EF和LINQ查询数据库。我有多个查询来根据应用程序中的用户权限过滤数据。

from p in db.EmployeeDetails
join i in db.EmployeeDept on p.DeptId equals i.DeptId into inst
from i in inst.DefaultIfEmpty()
join s in db.Employee on p.EmpId equals s.EmpId into manager
from s in manager.DefaultIfEmpty()
join e in db.EmpStatus on p.EnrollmentStatusID equals e.StatusID into estatus
from e in estatus.DefaultIfEmpty()
where p.SomeId== id && (p.IsActive == true || p.SomeStatus == null)
select new EmployeeBase
{
  //select list common to all queries. 
};

这是基本查询的示例。对此,如果用户属于特定角色,我需要再添加一个where子句,如果用户属于某个其他角色,则需要添加一个新表。我能够使用if ... else条件检查进行五个不同的查询。但是一个新的要求带来了更多的条件和更多的表格以及更多的条款,这使得代码如此重复,最终成为维护的噩梦。

我尝试了PredicateBuilder,但我不确定如何将PredicateBuilder与多个实体和外连接一起应用。

我从ScottGu的块中发现了动态LINQ库,但我不确定它是否有.Net 4.5版本,在这种情况下是有用的。

有没有办法可以动态构建查询,这样我就不需要在需求发生微小变化时更改每个查询。

1 个答案:

答案 0 :(得分:2)

public IQueryable<EmployeeBase> Employees() {
    return (

    from p in db.EmployeeDetails
    join i in db.EmployeeDept on p.DeptId equals i.DeptId into inst
    from i in inst.DefaultIfEmpty()
    join s in db.Employee on p.EmpId equals s.EmpId into manager
    from s in manager.DefaultIfEmpty()
    join e in db.EmpStatus on p.EnrollmentStatusID equals e.StatusID into estatus
    from e in estatus.DefaultIfEmpty()
    where p.SomeId== id && (p.IsActive == true || p.SomeStatus == null)
    select new EmployeeBase
    {
      //select list common to all queries. 
    });
}

...

var awesomeEmployee=Employees().Single(x=>x.name=="Me");
var listToFire=Employees().OrderByDescending(x=>x.Salary).Take(3);
var listToPromote=Employees().OrderByDescending(x=>x.Performance).Take(1);

虽然,我建议重复使用EF对象,并确保正确设置导航属性。从您的代码中看,您似乎根本就没有使用它们 - 这会让您陷入困境。你真的应该有这样的扩展方法:

public static IQueryable<EmployeeDetails> IsActive(this IQueryable<EmployeeDetails> eb) {
    return eb.Where(p=>p.IsActive == true || p.SomeStatus == null);
}

然后您可以访问以下数据:

var employee=db.EmployeeDetails
  .IsActive()
  .Include(x=>x.Manager);

foreach(var e in employee) { 
  Console.Writeline("{0}'s manager is {1}",
    e.name,
    e.Manager.name);
}