2010-11-11 40 views
1

我有以下型號:如何將謂詞<T>傳遞給Linq to SQL中的Where()方法?

+--------+ 
| Folder | 
+--------+ 
    | 1 
    | 
    | * 
+----------+   +---------+ 
| WorkItem |---------| Project | 
+----------+ *  1 +---------+ 

我需要檢索文件夾列表與工作項的當前計數。

如果我指定了一個項目,那麼我只希望在每個文件夾都與指定的項目相關的工作項的數量。

如果未指定項目,則應返回總WorkItem計數。

我有以下的LINQ to SQL代碼:

public interface IWorkItemCriteria { 
    int? ProjectId { get; } 
} 

public static IQueryable<Folder> GetFoldersWithItemCounts(IWorkItemCriteria criteria) { 
    var results = from folder in dataContext.Folders 
     select new { 
       Folder = folder, 
       Count = folder.WorkItems.Count() 
    }; 
    return(results); 
} 

的問題是 - 我想,以過濾被計算的工作項。

這工作:

var results = from folder in dataContext.Folders 
     select new { 
       Folder = folder, 
       Count = folder.WorkItems.Where(item => item.ProjectId == criteria.ProjectId).Count() 
    }; 

,但我不能讓它使用任何一種動態謂詞/表達。我試圖使用的語法爲:

var results = from folder in dataContext.Folders 
     select new { 
       Folder = folder, 
       Count = folder.WorkItems.Where(filter).Count() 
    }; 

我已經試過

Predicate<WorkItem> filter = (item => item.ProjectId == criteria.ProjectId); 

Expression<Func<WorkItem, bool>> filter = (item => item.ProjectId == criteria.ProjectId) 

均未將彙編 - 給The type arguments for method 'System.Linq.Enumerable.Where<TSource> (System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

我已經試過

Func<WorkItem, bool> filter = (item => item.ProjectId == criteria.ProjectId); 

它構建,但然後失敗'用於查詢運算符的不支持的過載'Where'。'

我將需要額外的屬性添加到IWorkItemCriteria接口,所以要動態構造可以通過LINQ的乾淨地轉換爲SQL謂詞的能力是非常重要的。

任何想法?

回答

1

我覺得你的問題是,你想與第二表達內引用一個表達式(過濾器)(一個是傳遞給results.Where.Select()),並且LINQ to SQL IQueryable提供程序不知道如何提取該值。

你將不得不做的是從頭開始編寫Select表達式,以便內嵌表達式是你的動態過濾器。對於匿名類型,這可能會非常困難,我不確定。我剛剛找到以下文章,似乎很好的解釋了這一點:http://www.codeproject.com/KB/linq/rewrite_linq_expressions2.aspx

+0

http://twitter.com/dylanbeattie/status/3051746305773568 :) – 2010-11-14 09:32:05

1

東西我抓住過MSDN的:這個想法是,你只需將它指向一個現有的功能:

使用系統;

公共類GenericFunc

{ 
    public static void Main() 
    { 
     Func<string, string> convertMethod = UppercaseString; 
    } 

    private static string UppercaseString(string inputString) 
    { 
     return inputString.ToUpper(); 
    } 
} 

我敢肯定還有其他的方法。我記得做了類似

new Func<WorkItem, bool>((item => item.projectId == criteria.ProjectId)) 

但我不確定。了,我敢肯定你所需要的「新」不過,希望這有助於:)