使用 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();
}
问题在于,在您的 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。您必须注意这一点,因为当您转换为列表时,查询将立即执行。您希望向数据库服务器发送单个查询。