代码之家  ›  专栏  ›  技术社区  ›  Jimmy W

从LINQ到SQL生成的T-SQL缺少where子句

  •  2
  • Jimmy W  · 技术社区  · 16 年前

    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 可能也有兴趣。

    1 回复  |  直到 9 年前
        1
  •  5
  •   Anders Abel    16 年前

    问题是函数

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

    接受 Func<...> 参数,这将使lambda编译成函数。linqtosqlsql生成器不能将编译后的函数转换为sql,而是在内存中执行过滤和投影。

    改变你的想法 lookupCodeInfo Expression<...> 相反,这将把它们保留为linqtosql可以遍历的表达式树。