簡體   English   中英

Linq:如何針對關聯對象使用規范

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM