动态或语句的 LINQ

9

今天我们有这样一份声明:

var Query = (from dp in db.Patients
            select dp);

var UserID = User.Identity.GetUserId();

if (User.IsInRole("Administrator"))
{
    Query = Query.Where(x => x.AdministratorID == UserID);
}
if (User.IsInRole("Counselor"))
{
    Query = Query.Where(x => x.CounselorID == UserID);
}
if (User.IsInRole("Physician"))
{
    Query = Query.Where(x => x.PhysicianID == UserID);
}

问题是我们有用户可以有多个角色。如果一个用户既是顾问又是医生,我们希望系统能够检索出所有CounselorID == UserID或PhsicianID == UserID的患者。

如果我们不知道在加载页面时用户将拥有什么角色,如何动态地完成这个任务?

当前的.Where子句只使用AND语句,我们需要一个OR语句。

理想情况下,解决方案应该像这样:

if (User.IsInRole("Administrator"))
{
     Query = Query.Where(x => x.AdministratorID == UserID);
}
if (User.IsInRole("Counselor"))
{
     Query = Query.WhereOr(x => x.CounselorID == UserID);
}
if (User.IsInRole("Physician"))
{
     Query = Query.WhereOr(x => x.PhysicianID == UserID);
}

你可以使用DynamicLinq或者使用Expression类来构建自定义谓词。 - Grundy
用户是否可以拥有 CounselorID == UserID 的情况,但没有辅导员角色? - JensB
可能重复的内容 LINQ - 动态 WHERE 子句 - Grundy
3个回答

20

你可以逐步构建一个谓词。

Func<Pantient, bool> predicate = p => false;

if (User.IsInRole("Administrator"))
{
    var oldPredicate = predicate;
    predicate = p => oldPredicate(p) || p.AdministratorID == UserID;
}

if (User.IsInRole("Counselor"))
{
    var oldPredicate = predicate;
    predicate = p => oldPredicate(p) || p.CounselorID == UserID;
}


var query = db.Patients.Where(predicate);

2
谢谢@dcastro,这帮助我找到了http://www.albahari.com/nutshell/predicatebuilder.aspx。 - Rob Carroll
我对变量 x 的来源感到困惑?似乎谓词构建应该在一个单独的方法中进行,但我很难弄清适当的方法签名。 - The Muffin Man
@TheMuffinMan 哎呀,应该是p而不是x。现在已经修复了。 - dcastro
@dcastro,这样就清楚多了。谢谢! - The Muffin Man

7
这个可以吗?
var query = Patients.Where(
    x => (User.IsInRole("Administrator") && x.AdministratorID == UserID)
      || (User.IsInRole("Counselor") && x.CounselorID == UserID)
      || (User.IsInRole("Physician") && x.PhysicianID == UserID)
    );

2

如果有其他人正在寻找不同的解决方案,我发现 linqkit 非常有用且易于使用。因此,在您的示例中,解决方案将类似于这样:

var predicate = PredicateBuilder.New<Patients>(true);

if (User.IsInRole("Administrator"))
{
     predicate = predicate.Or(x => x.AdministratorID == UserID);
}

if (User.IsInRole("Counselor"))
{
     predicate  = predicate.Or(x => x.CounselorID == UserID);
}

if (User.IsInRole("Physician"))
{
     predicate  = predicate.Or(x => x.PhysicianID == UserID);
}

query = query.Where(predicate)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接