有趣的 LinqToSql 行为

Posted

技术标签:

【中文标题】有趣的 LinqToSql 行为【英文标题】:Interesting LinqToSql behaviour 【发布时间】:2010-06-01 16:22:29 【问题描述】:

我们有一个数据库表,其中存储了一些波形文件的位置以及相关的元数据。表上有一个外键(employeeid)链接到一个员工表。但是,并非所有 wav 文件都与员工相关,因为这些记录的employeeid 为空。我们使用LinqToSQl访问数据库,查询拉出所有非员工相关的wav文件记录如下:

var results = from Wavs in db.WaveFiles
              where Wavs.employeeid == null;

除此之外,不返回任何记录,尽管存在employeeid 为空的记录。在分析 sql server 时,我发现没有返回记录的原因是因为 LinqToSQl 正在将其转换为看起来非常像的 SQL:

SELECT Field1, Field2 //etc
FROM WaveFiles
WHERE 1=0

显然这不会返回任何行。但是,如果我进入 DBML 设计器并删除关联并保存。突然之间完全相同的 LINQ 查询变成了

SELECT Field1, Field2 //etc
FROM WaveFiles
WHERE EmployeeID IS NULL

即如果存在关联,则 LinqToSql 假定所有记录都具有外键的值(即使它可以为空,并且该属性在 WaveFile 实体上显示为可以为空的 int),并且因此构造了一个不会返回任何记录的 where 子句.

有谁知道是否有办法在 LinqToSQL 中保持关联但停止这种行为。我能很快想到的一种解决方法是有一个名为 IsSystemFile 的计算字段,如果employeeid 为空,则将其设置为1,否则设置为0。然而,这似乎有点像解决 LinqToSQl 的奇怪行为的技巧,我宁愿在 DBML 文件中做一些事情,或者在外键约束上定义一些东西来防止这种行为。

【问题讨论】:

【参考方案1】:

我认为您应该仔细检查您的 dbml 文件。听起来 Linq 不知道 employeeid 是一个可为空的列。或者查看您的 .cs 文件。此列的属性应如下所示:

[Column(Storage="_employeeid", DbType="Int")]

而不是:

[Column(Storage="_employeeid", DbType="Int NOT NULL")]

【讨论】:

【参考方案2】:

试试这个:

var results = from Wavs in db.WaveFiles
              where DbNull.Value.Equals(Wavs.employeeid)

另一种很好的做法是引入一个默认员工,每个波形文件都关联到该员工,而该员工与真正的员工没有关联

【讨论】:

【参考方案3】:

列定义为:

[Column(Storage="_employeeid", DbType="Int")]

离开关联的方法是从员工实体集合中进行左连接。

【讨论】:

以上是关于有趣的 LinqToSql 行为的主要内容,如果未能解决你的问题,请参考以下文章

SQL 'Execute As' 登录命令和 Linq to SQL

.net 实体框架与 LinqToSql 相比如何?

截断表的正确 LINQtoSQL 方式是啥?

LinqToSql初探

使用新的架构更改更新 LinqtoSql 数据库?

LINQ To SQL