【问题标题】:T-SQL generated from LINQ to SQL is missing a where clause从 LINQ to SQL 生成的 T-SQL 缺少 where 子句
【发布时间】:2011-02-16 13:10:24
【问题描述】:

我有一个名为“CodeLookupAccessDataContext”的 DataContext 对象,它是通过 Visual Studio LINQ to SQL 类向导生成的。我扩展了这个对象的功能,使它公开了一些方法来返回 LINQ to SQL 查询的结果。以下是我定义的方法:

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 函数以指定要返回的行/列。

更新

This discussion 也可能感兴趣。

【问题讨论】:

    标签: c# .net linq-to-sql


    【解决方案1】:

    问题在于函数

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

    接受Func&lt;...&gt; 参数,这将使lambdas 编译成函数。 Linq-to-sql SQL 生成器无法将编译后的函数转换为 SQL,而是在内存中执行过滤和投影。

    将您的 lookupCodeInfo 更改为 Expression&lt;...&gt;,这会将它们保留为 linq-to-sql 可以遍历的表达式树。

    【讨论】:

    • 更重要的是,LINQ-to-SQL 从未被要求这样做;通过给它一个Func&lt;&gt;,您正在使用Enumerable.Where,而不是Queryable.Where,因此切换到LINQ-to-Objects。所以这不是完全“它不能”(虽然你是对的:它不能)
    • 感谢有用的提示,尤其是对正在发生的事情的解释(这正是我所寻找的)。使用 LINQ to Objects 时,我必须编译我的表达式。我假设这同样适用于 LINQ to SQL,这解释了我的困惑。
    猜你喜欢
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 2016-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    相关资源
    最近更新 更多