使用 Linq 联接列表返回的结果与相应的 SQL 查询不同

本文关键字:SQL 查询 结果 Linq 列表 返回 使用 | 更新日期: 2023-09-27 18:35:43

我有 2 个表

表一:

TableAID int,
Col1 varchar(8)

表B:

TableBID int
Col1 char(8),
Col2 varchar(40)

当我对 2 个表运行 SQL 查询时,它返回以下行数

SELECT * FROM tableA (7200 rows)
select * FROM tableB (28030 rows)

当联接在 col1 上并选择数据时,它将返回以下行数

select DISTINCT a.Col1,b.Col2 FROM tableA a
join tableB b on a.Col1=b.Col1 (6578 rows)
以上 2 个

表在不同的数据库上,所以我创建了 2 个 EF 模型并分别重试数据,并尝试使用 linq 使用以下函数将它们联接到代码中。令人惊讶的是,它返回 2886 条记录而不是 6578 条记录。我做错了什么吗?各个列表似乎返回了正确的数据,但是当我加入它们时,SQL查询和linq查询的记录数有所不同。

对此的任何帮助都非常感谢。

// This function is returning 2886 records      
public List<tableC_POCO_Object> Get_TableC() 
{
    IEnumerable<tableC_POCO_Object> result = null;
    List<TableA> tableA_POCO_Object = Get_TableA(); // Returns 7200 records
    List<TableB> tableB_POCO_Object = Get_TableB(); // Returns 28030 records
    result = from tbla in tableA_POCO_Object
         join tblb in tableB_POCO_Object on tbla.Col1 equals tblb.Col1
         select new tableC_POCO_Object 
         {
         Col1 = tblb.Col1,
         Col2 = tbla.Col2
         };
    return result.Distinct().ToList();
}

使用 Linq 联接列表返回的结果与相应的 SQL 查询不同

问题在于,在您的 POCO 世界中,您尝试使用直接比较来比较两个字符串(这意味着它区分大小写)。这可能适用于 SQL 世界(当然,除非您启用了区分大小写),但当您有 "stringA" == "StringA" 时就不太好用了。您应该做的是将连接列规范化为全部大写或小写:

join tblb in tableB_POCO_Object on tbla.Col1.ToUpper() equals tblb.Col1.ToUpper()

Join 运算符使用指定的键(从第二个集合开始)创建查找,并通过检查生成的查找将原始表/集合联接回来,因此如果哈希值不同,它们将不会连接。

关键是,在字符串数据/属性上联接 OBJECT 集合是不好的,除非您规范化为相同的 cAsE。对于 LINQ 到某些数据库提供程序,如果数据库不区分大小写,则这无关紧要,但在 CLR/L2O 世界中始终很重要。

编辑:啊,没有意识到它是CHAR(8)而不是VARCHAR(8),这意味着无论如何它都会填充到 8 个字符。在这种情况下,tblb.Col1.Trim()将解决您的问题。但是,在处理 LINQ to Objects 查询时,仍要记住这一点。

这可能是因为您比较了VARCHAR列和CHAR列。在 SQL 中,这取决于 sql 服务器上ANSI_PADDING的设置,而在 C# 中,使用 DataReader 读取字符串值并使用标准字符串函数进行比较。

尝试在 LINQ 语句中tblb.Col1.Trim()

正如SPFiredrake正确指出的那样,这可能是由区分大小写引起的,但我也必须问你为什么以这种方式编写代码,为什么不是这样:

// This function is returning 2886 records      
public List<tableC_POCO_Object> Get_TableC() 
{
    return from tbla in Get_TableA()
           join tblb in Get_TableB() on tbla.Col1 equals tblb.Col1
           select new tableC_POCO_Object 
           {
             Col1 = tblb.Col1,
             Col2 = tbla.Col2
           }.Distinct().ToList();
}

其中 Get_TableA() 和 Get_TableB() 返回 IEnumerable 而不是 List。您必须注意这一点,因为当您转换为列表时,查询将立即执行。您希望向数据库服务器发送单个查询。