![](/img/trans.png)
[英]Using Linq, how to GroupBy against objects in a list within the target object
[英]Linq: how to use specifications against associated objects
我正在使用这种形式的规格:
public static Expression<Func<User, bool>> IsSuperhero
{
get
{
return x => x.CanFly && x.CanShootLasersFromEyes;
}
}
现在我可以在表单中使用此规范:
var superHeroes = workspace.GetDataSource<User>().Where(UserSpecifications.IsSuperhero);
但是我不确定如何对这样的关联对象使用规范:
var loginsBySuperheroes = workspace.GetDataSource<Login>().Where(x => x.User [ ??? ]);
有没有办法做到这一点,还是我需要重新考虑我的规范实施?
实际上,您需要创建一个Expression<Func<Login, bool>>
,它从Login中收集关联的User,然后在该用户上应用现有的IsSuperhero
谓词。 实现此目的的规范方法是在“包含”表达式(本例中为IsSuperHero
)上使用Expression.Invoke
,用适当的参数替换其参数。
不幸的是,这种方法手工操作相当混乱。 更糟糕的是,许多LINQ提供程序,例如LINQ to Entities,根本不喜欢这种“表达式内部表达”方法。 解决这个问题的办法是“内联”的“调用”表达成更大的表达,使这一切看起来像一个单一的 ,巨大的,表达树。
Fortuantely,有一个方便的库LINQKit可以帮助解决这个问题:
#region LINQKit Magic
Expression<Func<Login, bool>> predicate = login => IsSuperHero.Invoke(login.User);
var expandedPredicate = predicate.Expand();
#endregion LINQKit Magic
var loginsBySuperheroes = workspace.GetDataSource<Login>().Where(expandedPredicate);
明显:
var loginsBySuperheroes = workspace.GetDataSource<User>()
.Where(UserSpecifications.IsSuperhero)
.SelectMany(x => x.Logins);
这很有趣:
var secretBillionaires = workspace.GetDataSource<User>()
.Where(UserSpecifications.IsSuperhero)
.SelectMany(user => user.Logins)
.Where(LoginSpecifications.IsSecretIdentity)
.Select(login => login.DayJob)
.Where(DayJobSpecifications.IsBillionaire)
我相信你需要编译然后调用表达式:
var loginsBySuperheroes = GetLogins().Where(l => IsSuperhero.Compile().Invoke(l.User));
另一种方法是预编译表达式:
var f = IsSuperhero.Compile();
var loginsBySuperheroes = GetLogins().Where(l => f(l.User));
您可以创建自己的自定义QueryProvider,如下所述: http : //msdn.microsoft.com/en-us/library/bb546158.aspx
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.