我正在使用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 是一个可为空的整数,因此要比较的属性也是如此r.selected_last_part_url_id 的类型为 int,所比较的属性也是如此r.language_id 的类型为 int,所比较的属性也是如此
第一个查询是在内存中完成的,因为您使用的是 Enumerable.FirstOrDefault(...(。第二个查询由数据上下文转换为 SQL,并由数据库执行。
您必须检查 sql 探查器以查看执行的实际查询是什么,以了解差异是什么。数据库中是否有任何可为空的列可能是问题所在?
更新
如果在转换为 SQL 语句的表达式中比较可为 null 的属性,请注意,如果比较的两个值均为 null,则可能会出错。例:
_dataContext.StaticPageLangs
.FirstOrDefault(r => r.selected_partial_url_id == partialUrlid)
如果部分 Urlid == NULL 并且存在具有 selected_partial_url_id == NULL 的记录,则不会生成任何记录。原因:翻译后的 sql 包含"selected_partial_url_id == NULL"而不是"selected_partial_url_id IS NULL"。
:以下答案适用于record1
null
和record2
不null
,这与问题相反,但可能对其他具有类似场景的读者有用。
如果我不得不猜测,这些==
中至少有一个在string
上,这是一个区分大小写的问题。
record1
来自 LINQ to-Objects,因此它从服务器中提取所有行,并在本地测试它们。然后,这些==
区分大小写(string
上的 C#/.NET ==
始终区分大小写(。
record2
看起来它正在通过 IQueryable<>
使用数据库实现。这意味着它正在被翻译成 TSQL。SQL 服务器数据库可以区分大小写或不区分大小写。我猜你把它设置为不区分大小写。
现在想象一下,languageId
在 C# 中"en-us"
,'EN-US'
在数据库中。
这可能导致record1
成为null
,但record2
被填补。