有谁可以解释我在以下2个查询中的区别?

时间:2012-07-25 12:24:40

标签: c# .net linq linq-to-sql sqlmetal

我正在使用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_pa​​rtial_url_id是一个可以为空的int,因此被比较的属性也是如此 r.selected_last_part_url_id属于int类型,因此被比较的属性 r.language_id的类型为int,因此被比较的属性

2 个答案:

答案 0 :(得分:5)

第一个查询是在内存中完成的,因为您使用的是Enumerable.FirstOrDefault(...)。 第二个查询由数据上下文转换为SQL,由数据库执行。

您必须检查sql profiler以查看执行的实际查询是什么,以查看区别。数据库中任何可以为空的列都可能出现问题?

更新

如果比较转换为SQL语句的表达式中的可空属性,请注意如果比较的两个值都为null,则可能会出错。例如:

_dataContext.StaticPageLangs
    .FirstOrDefault(r => r.selected_partial_url_id == partialUrlid)
如果partialUrlid == NULL并且存在selected_pa​​rtial_url_id == NULL的记录,

将不会产生任何记录。原因:翻译的sql包含'selected_pa​​rtial_url_id == NULL'而不是'selected_pa​​rtial_url_id IS NULL'。

答案 1 :(得分:1)

注意:以下答案适用于record1 nullrecord2不是null,这与问题相反,但可能有用对于具有类似场景的其他读者

如果我不得不猜测,==中至少有一个string位于record1,这是一个区分大小写的问题。

==来自LINQ-to-Objects,所以它从服务器中提取所有行,并在本地测试它们。那些==然后区分大小写(string上的C#/ .NET record2始终区分大小写。)

IQueryable<>看起来正在通过languageId使用数据库实现。这意味着它正在被转换为TSQL。 SQL-Server数据库可以区分大小写或不区分大小写。我猜你已将它设置为不区分大小写。

现在想象一下,"en-us"在C#中是'EN-US',在数据库中是record1

这可能导致null成为record2,但{{1}}正在填补。