2014-06-23 38 views
1

Lambda表達式我有一個具有以下簽名的擴展方法:兩個IN參數Lambda表達式與單個IN參數

public static class GenericSeeder 
{ 
    public static void Seed<TSeed, TEntity>(this DbContext context, IEnumerable<TSeed> seeds, Expression<Func<TEntity, TSeed, bool>> predicate) 
    { 
     // code that I'm looking for goes here 
    } 
} 

爲了有更好的理解什麼方法做的,這裏是它應該如何使用:

context.Seed<SeedClass, EntityClass>(seeds, (entity, seed) => entity.Name == seed.OtherProperty); 

所以基本上,我使用謂詞來檢查種子是否已經被應用。然而,爲了做一次檢查,我必須用在哪裏或FirstOrDefault從LINQ到實體,它採用以下的參數:

Expression<Func<TEntity, bool>> predicate 

所以我的lambda表達式是2 IN參數(TSeed,TEntity)已與功能1 OUT參數(布爾)。我需要遍歷提供的TSeed對象集合,併爲每個對象使用該對象作爲我的lambda表達式的參數,以生成具有1個IN參數(TEntity)和1個OUT參數(bool)的LINQ 2實體lambda表達式。

有沒有辦法做一個部分調用lambda表達式/ func來獲得另一個lambda表達式/ func?

+0

雖然我想我知道你在問什麼我不是100%肯定。你可以使用類似'(x,y)=> {x.Frob(); return y == x;}'或類似的東西來做多語句lambdas(編譯得很好,可能不會用真正的編譯器)。這可以讓你在內部做只有一個屬性,然後是另一個屬性的東西。我不能保證除了linq之外的任何linq提供者都能夠做到這一點(並且實際上可能不會)。 – Chris

+0

謂詞中的比較始終是'=='? –

回答

1

通過使用LINQKit的允許表達式以這樣的方式來調用的他們將被轉化爲其他表達式你的方法的執行變得相當瑣碎:

public static IQueryable<TEntity> Seed<TSeed, TEntity>(
    this DbContext context, 
    IEnumerable<TSeed> seeds, 
    Expression<Func<TEntity, TSeed, bool>> predicate) 
{ 
    return context.Set<TEntity>() 
      .AsExpandable() 
      .Where(entity => seeds.Any(seed => predicate.Invoke(entity, seed))); 
} 
+0

對不起,雖然您的答案有一個值(因此upvote )針對特定場景,對於我的場景,由於其餘的實施情況,它並不是最優化的。您可能將時間花在表達T-SQL轉換上,但另一方面,我會再次遍歷查詢結果併爲每個種子找到匹配的實體(因爲您一次只能查詢所有內容如果使用太多種子,可能會非常大)。 –

+0

@BarisaPuter如果你的方法接受適當的投影作爲參數,或者簡單地期望調用者對給定輸出的種子進行分組,則可以通過種子值容易地將實體分組。花費在分組值上的努力不是特別大。如果你有很多種子,那麼做大量的數據庫往返取回都是一個大問題。這些往返行程都非常昂貴。 – Servy

0

我不知道你在做什麼,但是這是你如何在C#中做的部分應用程序:

Func<int,bool, string> twoInFunc= (int a, bool b) => a.ToString() + b.ToString(); 

int number = 7; 

Func<bool, string> oneInFunc= (bool b) => twoInFunc(number,b); 
+0

不幸的是你的解決方案並沒有幫助我,因爲我需要表達式轉換,因爲Linq 2實體的要求。如果我嘗試了你的建議,我最終得到:LINQ to Entities不支持LINQ表達式節點類型「Invoke」。 –

0

我已經成功地創建自己的解決方案。然而,我確實使用臭名昭着的LinqKit擴展庫,它是AsExpandable()擴展方法。

LinqKit可以在這裏找到:NuGet link

所以這是一個使用LINQ 2實體工程的實施:

public static void Seed<TSeed, TEntity>(this DbContext context, IEnumerable<TSeed> seeds, Expression<Func<TEntity, TSeed, bool>> predicate) 
      where TEntity : class 
      where TSeed : class 
     { 
      foreach (TSeed seed in seeds) 
      { 
       Expression<Func<TEntity, bool>> matchExpression = (entity) => predicate.Invoke(entity, seed); 
       TEntity existing = context.Set<TEntity>().AsExpandable().FirstOrDefault(matchExpression); 

      // Rest of code is omitted as it is not related to the original question. 
      // The query above is properly executed by Linq 2 Entities. 
      } 
     } 
+0

這是將查詢評估爲每個種子的值。你不應該那樣做。 – Servy

+0

@Servy你能提供更好的解決方案嗎? –

+0

是的,我可以提供更好的解決方案。 – Servy