2010-05-06 44 views
2

我有一個通過Visual Studio LINQ to SQL類嚮導生成的名爲「CodeLookupAccessDataContext」的DataContext對象。我擴展了這個對象的功能,以便公開一些方法來返回LINQ to SQL查詢的結果。下面是我所定義的方法:從LINQ到SQL生成的T-SQL缺少where子句

public List<CompositeSIDMap> lookupCompositeSIDMap(int regionId, int marketId) 
{ 
    var sidGroupId = CompositeSIDGroupMaps.Where(x => x.RegionID.Equals(regionId) && x.MarketID.Equals(marketId)) 
     .Select(x => x.CompositeSIDGroup); 

    IEnumerator<int> sidGroupIdEnum = sidGroupId.GetEnumerator(); 

    if (sidGroupIdEnum.MoveNext()) 
     return lookupCodeInfo<CompositeSIDMap, CompositeSIDMap>(x => x.CompositeSIDGroup.Equals(sidGroupIdEnum.Current), x => x); 
    else 
     return null; 
} 

private List<TResult> lookupCodeInfo<T, TResult>(Func<T, bool> compLambda, Func<T, TResult> selectLambda) 
    where T : class 
{ 
    System.Data.Linq.Table<T> dataTable = this.GetTable<T>(); 

    var codeQueryResult = dataTable.Where(compLambda) 
     .Select(selectLambda); 

    List<TResult> codeList = new List<TResult>(); 
    foreach (TResult row in codeQueryResult) 
     codeList.Add(row); 

    return codeList; 
} 

CompositeSIDGroupMap和CompositeSIDMap在我們的數據庫中的表都被表示爲我的DataContext對象的對象。我寫了下面的代碼來調用這些方法並顯示T-SQL生成調用這些方法後:

using (CodeLookupAccessDataContext codeLookup = new CodeLookupAccessDataContext()) 
{ 
    codeLookup.Log = Console.Out; 
    List<CompositeSIDMap> compList = codeLookup.lookupCompositeSIDMap(regionId, marketId); 
} 

我在我的日誌中出現以下結果調用此代碼後:

SELECT [t0].[CompositeSIDGroup] 
FROM [dbo].[CompositeSIDGroupMap] AS [t0] 
WHERE ([t0].[RegionID] = @p0) AND ([t0].[MarketID] = @p1) 
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [5] 
-- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [3] 
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1 

SELECT [t0].[PK_CSM], [t0].[CompositeSIDGroup], [t0].[InputSID], [t0].[TargetSID], [t0].[StartOffset], [t0].[EndOffset], [t0].[Scale] 
FROM [dbo].[CompositeSIDMap] AS [t0] 
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1 

第一T-SQL語句包含指定的where子句並按預期返回一列。然而,第二條語句缺少where子句並返回所有列,即使我確實指定了我想要查看的行和哪些列感興趣。爲什麼第二個T-SQL語句的生成方式是這樣的,我應該怎麼做以確保通過T-SQL按照規範過濾掉數據?

另請注意,我寧願保留lookupCodeInfo(),特別是希望使其能夠接受用於指定要返回的行/列的lambda函數。

UPDATE

This discussion也可能會感興趣。

回答

5

的問題是,該功能

private List<TResult> lookupCodeInfo<T, TResult>(Func<T, bool> compLambda, 
               Func<T, TResult> selectLambda) 

接受Func<...>參數,這將使編譯成函數的lambda表達式。 Linq-to-SQL SQL生成器不能將編譯函數轉換爲SQL,而是執行內存中的過濾和投影。

改變你的lookupCodeInfo代替Expression<...>,它會將它們保存爲linq-to-sql可以遍歷的表達式樹。

+3

更重要的是,LINQ-to-SQL *從來沒有被要求*做到這一點;通過給它一個'Func <>'你正在使用'Enumerable.Where',而不是'Queryable.Where',因此切換到LINQ-to-Objects。所以它不*相當*只是「它不能」(雖然你是對的:它不能) – 2010-05-06 19:52:53

+0

感謝有用的提示,尤其是關於發生了什麼事情的解釋(這真的是我正在尋找的東西對於)。當使用LINQ到對象時,我不得不編譯我的表達式。我認爲這同樣適用於LINQ to SQL,這解釋了我的困惑。 – 2010-05-07 12:13:31