我正在使用SqlMetal(linq to sql)来从数据库中检索内容。 但是,使用以下代码获得不同的结果:
var record1 = Enumerable.FirstOrDefault(_dataContext.StaticPageLangs,
r => r.selected_partial_url_id == partialUrlid
&& r.selected_last_part_url_id == lastPartUrlId
&& r.language_id == languageId);
var record2 = _dataContext.StaticPageLangs.FirstOrDefault(
r => r.selected_partial_url_id == partialUrlid
&& r.selected_last_part_url_id == lastPartUrlId
&& r.language_id == languageId);
在填充此记录1之后,但是记录2为NULL,我希望它们是相同的。
有人可以解释这个区别吗?
修改
旁注:
r.selected_partial_url_id是一个可以为空的int,因此被比较的属性也是如此 r.selected_last_part_url_id属于int类型,因此被比较的属性 r.language_id的类型为int,因此被比较的属性
答案 0 :(得分:5)
第一个查询是在内存中完成的,因为您使用的是Enumerable.FirstOrDefault(...)。 第二个查询由数据上下文转换为SQL,由数据库执行。
您必须检查sql profiler以查看执行的实际查询是什么,以查看区别。数据库中任何可以为空的列都可能出现问题?
更新
如果比较转换为SQL语句的表达式中的可空属性,请注意如果比较的两个值都为null,则可能会出错。例如:
_dataContext.StaticPageLangs
.FirstOrDefault(r => r.selected_partial_url_id == partialUrlid)
如果partialUrlid == NULL并且存在selected_partial_url_id == NULL的记录,将不会产生任何记录。原因:翻译的sql包含'selected_partial_url_id == NULL'而不是'selected_partial_url_id IS NULL'。
答案 1 :(得分:1)
注意:以下答案适用于record1
null
而record2
不是null
,这与问题相反,但可能有用对于具有类似场景的其他读者。
如果我不得不猜测,==
中至少有一个string
位于record1
,这是一个区分大小写的问题。
==
来自LINQ-to-Objects,所以它从服务器中提取所有行,并在本地测试它们。那些==
然后区分大小写(string
上的C#/ .NET record2
始终区分大小写。)
IQueryable<>
看起来正在通过languageId
使用数据库实现。这意味着它正在被转换为TSQL。 SQL-Server数据库可以区分大小写或不区分大小写。我猜你已将它设置为不区分大小写。
现在想象一下,"en-us"
在C#中是'EN-US'
,在数据库中是record1
。
这可能导致null
成为record2
,但{{1}}正在填补。