![](/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.