从LINQ到SQL生成的T-SQL缺少where子句
问题描述:
我有一个通过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也可能会感兴趣。
答
的问题是,该功能
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可以遍历的表达式树。
更重要的是,LINQ-to-SQL *从来没有被要求*做到这一点;通过给它一个'Func '你正在使用'Enumerable.Where',而不是'Queryable.Where',因此切换到LINQ-to-Objects。所以它不*相当*只是“它不能”(虽然你是对的:它不能) – 2010-05-06 19:52:53
感谢有用的提示,尤其是关于发生了什么事情的解释(这真的是我正在寻找的东西对于)。当使用LINQ到对象时,我不得不编译我的表达式。我认为这同样适用于LINQ to SQL,这解释了我的困惑。 – 2010-05-07 12:13:31