C# 使用Linq连接列表会返回与相应SQL查询不同的结果吗?
我有两张桌子 表a:C# 使用Linq连接列表会返回与相应SQL查询不同的结果吗?,c#,C#,我有两张桌子 表a: TableAID int, Col1 varchar(8) 表B: TableBID int Col1字符(8), Col2 varchar(40) 当我在这两个表上运行SQL查询时,它返回以下行数 select DISTINCT a.Col1,b.Col2 FROM tableA a join tableB b on a.Col1=b.Col1 (6578 rows) 从表A中选择*(7200行) 从表B中选择*(28030行) 在col1上联接并选择数据时,它返
TableAID int,
Col1 varchar(8)
表B:
TableBID int
Col1字符(8),
Col2 varchar(40)
当我在这两个表上运行SQL查询时,它返回以下行数
select DISTINCT a.Col1,b.Col2 FROM tableA a
join tableB b on a.Col1=b.Col1 (6578 rows)
从表A中选择*(7200行)
从表B中选择*(28030行)
在col1上联接并选择数据时,它返回以下行数
select DISTINCT a.Col1,b.Col2 FROM tableA a
join tableB b on a.Col1=b.Col1 (6578 rows)
以上两个表位于不同的数据库上,因此我创建了两个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();
}
//此函数返回2886条记录
公共列表获取_TableC()
{
IEnumerable结果=null;
List tableA_POCO_Object=Get_tableA();//返回7200条记录
List tableB_POCO_Object=Get_tableB();//返回28030条记录
结果=来自tableA\u POCO\u对象中的tbla
在tbla.Col1上的tableB_POCO_对象中加入tblb等于tblb.Col1
选择新的tableC\u POCO\u对象
{
Col1=tblb.Col1,
Col2=tbla.Col2
};
返回result.Distinct().ToList();
}
问题在于,在您的POCO世界中,您试图使用直接比较来比较两个字符串(这意味着它区分大小写)。这在SQL世界中可能会起作用(当然,除非您启用了区分大小写),但在使用“stringA”==“stringA”
时,效果不太好。您应该做的是将联接列规范化为全部大写或小写:
join tblb in tableB_POCO_Object on tbla.Col1.ToUpper() equals tblb.Col1.ToUpper()
Join操作符使用指定的键(从第二个集合开始)创建一个查找,并通过检查生成的查找将原始表/集合连接回来,因此如果哈希值不同,它们将不会连接
关键是,除非规范化为相同的情况,否则在字符串数据/属性上连接对象集合是不好的。对于LINQ到某些DB提供程序,如果数据库不区分大小写,那么这并不重要,但在CLR/L2O世界中它总是很重要的
编辑:啊,我没有意识到它是
CHAR(8)
而不是VARCHAR(8)
,这意味着无论发生什么情况,它都会填充到8个字符。在这种情况下,tblb.Col1.Trim()
将解决您的问题。但是,在处理LINQ to Objects查询时仍要记住这一点。这可能是因为比较了VARCHAR
和CHAR
列。在SQL中,这取决于SQL server上的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();
}
//此函数返回2886条记录
公共列表获取_TableC()
{
在Get_TableA()中从tbla返回
在tbla.Col1上的Get_TableB()中加入tblb等于tblb.Col1
选择新的tableC\u POCO\u对象
{
Col1=tblb.Col1,
Col2=tbla.Col2
}.Distinct().ToList();
}
其中Get_TableA()和Get_TableB()返回IEnumerable而不是List。您必须注意这一点,因为当您转换为列表时,查询将立即执行。您想向数据库服务器发送一个查询。在linq中返回tblb.Col1和tbla.Col2是否有关系,但在SQL中返回tbla.Col1和tblb.Col2?不,没有,我尝试了这些组合。tableC_POCO_对象只包含两个属性Col1和Col2?是的,您是正确的,即使我返回tableA_POCO_对象或tableB_POCO_对象,返回的记录数也保持不变。因此,在返回之前,请尝试执行:
var sql=((System.Data.Objects.ObjectQuery)result.)ToTraceString()
并查看sql是什么。感谢您的建议,尝试了上述操作但没有成功,返回的记录数仍然没有更改。当然,注意点将按照建议对代码进行更改。但我最初的问题仍未解决。