如何使用Linq-to-SQL删除具有空外键的行?

时间:2013-07-10 16:35:07

标签: c# sql-server linq-to-sql foreign-keys nullable

我有一个名为tblOvrdImpVolsType的表,其中有两个可以为空的外键列。当此行中的一个外键列为空时,我在使用Linq-To-SQL删除此表中的行时遇到问题。这是我的代码:

using (Databases.Global db = new Databases.Global())
{
    db.Log = Console.Out;
    var records = from iv in db.tblOvrdImpVolsType
                    join sm in db.tblSecurityMasterType 
                       on iv.FkSecurity equals sm.PkSecurity
                    where sm.Name == name
                    select iv; //returns only 1 record

    db.tblOvrdImpVolsType.DeleteAllOnSubmit<MyTableType>(records);

    int numDeletes = db.GetChangeSet().Deletes.Count; // = 1
    db.SubmitChanges(); //deletes 0 records
}
  • Databases.Global继承自DataContext并拥有我使用的表。

  • tblOvrdImpVolsType有两个可以为空的外键列(key1和key2)

  • 我感兴趣的行有这些键值(key1 = 9898,key2 = null)

  • 在我的C#代码中,key1和key2的数据类型都是int?CanBeNull = true

  • GetChangeSet()显示将删除一条记录,但当我检查数据库时,该行显然不会被删除。

  • 不会抛出异常。

这是DataContext生成的SQL:

DELETE FROM [tblOvrdImpVols] WHERE ([key1] = @p0) AND ([key2] = @p1)
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [9898]
-- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [Null]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.17929

我认为问题是[key2] = @p1部分。因为我感兴趣的key2值为null,所以SQL很糟糕。下面的这些SQL查询说明了这一点唯一的区别是is条件中的=key2

select * FROM [tblOvrdImpVols] WHERE ([key1] = 9898) AND ([key2] is null)
    --returns 1 row

select * FROM [tblOvrdImpVols] WHERE ([key1] = 9898) AND ([key2] = null)
    --returns 0 rows

我做错了什么?我假设如果我可以使用DataContext对象将=替换为is以获取空值,则删除将起作用。我不知道该怎么做。我也认为之前已经问过这个问题,但我找不到它。

编辑:我最初称我的钥匙是“主要”而不是“外国”。我打算说“外国人”。我编辑我的帖子说“外国”。我仍然遇到同样的问题。

2 个答案:

答案 0 :(得分:0)

为了确保您还捕获空值,您可以将查询修改为如下所示:

select * FROM [tblOvrdImpVols] 
WHERE ([key1] = @p0) AND 
([key2] = @p1 OR 
    ([key2] is null and @p1 is null) )

答案 1 :(得分:0)

这里的主要问题-在SQL中,没有什么等于NULL。 NULL甚至不等于它本身!在SQL查询中,“ NULL = NULL”将评估为“ false”。因此,当您需要删除[key2] == null的行时,您需要编写LINQ查询,该查询将生成类似SQL的

“哪里[key2] = @ p1 AND [key2]为空”

代替

“ [key2] = @ p1 AND [key2] = @ p2”。

该怎么做?似乎正确的方法是将[key2]与null进行比较。 例如,如果您想从tblSecurityMasterType中获取所有行,其中Name为NULL,这将是错误的方式:

string NameNull = null;
from sm in db.tblSecurityMasterType 
     where sm.Name == NameNull
     select sm;

您将需要改用以下查询:

from sm in db.tblSecurityMasterType 
     where sm.Name == null
     select sm;

此处描述:http://smsohan.com/blog/2008/08/05/comparing-with-null-in-where-clause-in/