代码之家  ›  专栏  ›  技术社区  ›  Coding Flow

有趣的LinqToSQL行为

  •  3
  • Coding Flow  · 技术社区  · 15 年前

    我们有一个数据库表,它存储了一些wave文件以及相关元数据的位置。表中有一个外键(EmployeeID)链接到Employee表。但是并非所有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),因此delivery构造了一个不会返回任何记录的where子句。

    是否有人知道linqtosql中是否有保持关联的方法,但要停止这种行为。我可以快速想到的一个解决方法是使用一个名为ISSystemFile的计算字段,如果EmployeeID为空,则将其设置为1,否则设置为0。然而,这看起来有点像是围绕LinqToSQL的奇怪行为进行的一次黑客攻击,我宁愿在DBML文件中做一些事情,或者在外键约束上定义一些阻止这种行为的东西。

    3 回复  |  直到 15 年前
        1
  •  5
  •   Keltex    15 年前

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

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

    而不是:

    [Column(Storage="_employeeid", DbType="Int NOT NULL")]
    
        2
  •  0
  •   kamahl    15 年前

    试试这个:

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

    另一种方法和良好的实践一个好方法是引入一个默认的雇员,其中每个wave文件都与之关联,而这个默认雇员与真正的雇员没有关联。

        3
  •  0
  •   Coding Flow    15 年前

    列定义为:

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

    离开关联时绕过它的方法是从雇员实体集合执行左联接。