我正在尝试使用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版本,在这种情况下是有用的。
有没有办法可以动态构建查询,这样我就不需要在需求发生微小变化时更改每个查询。
答案 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);
}