简体   繁体   English

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

[英]How do I delete a row with a null foreign key using Linq-to-SQL?

I have a table called tblOvrdImpVolsType with two foreign key columns that are both nullable. 我有一个名为tblOvrdImpVolsType的表, tblOvrdImpVolsType包含两个可以为空的外键列。 I'm having trouble deleting a row in this table using Linq-To-SQL when one of the foreign key columns in this row is null. 当此行中的一个外键列为空时,我在使用Linq-To-SQL删除此表中的行时遇到问题。 Here's my code: 这是我的代码:

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 inherits from DataContext and has the tables that I use. Databases.Global继承自DataContext并具有我使用的表。

  • tblOvrdImpVolsType has two nullable, foreign key columns (key1 and key2) tblOvrdImpVolsType有两个可以为空的外键列(key1和key2)

  • the row I am interested has these key values (key1 = 9898, key2 = null) 我感兴趣的行有这些键值(key1 = 9898,key2 = null)

  • In my C# code, the datatypes of key1 and key2 are both int? 在我的C#代码中,key1和key2的数据类型都是int? and CanBeNull = true CanBeNull = true

  • The GetChangeSet() shows that one record will be deleted, but when I check the database, that row is clearly not deleted. GetChangeSet()显示将删除一条记录,但是当我检查数据库时,该行显然不会被删除。

  • No exceptions are thrown. 没有异常被抛出。

Here is the SQL that the DataContext generates: 这是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

I think the problem is the [key2] = @p1 part. 我认为问题是[key2] = @p1部分。 Because the key2 value I'm interested in is null, the SQL is bad. 因为我感兴趣的key2值为null,所以SQL很糟糕。 These SQL queries below illustrate this. 下面的这些SQL查询说明了这一点 The only difference is the is vs. = in the key2 condition: 唯一的区别是key2条件中的is vs. =

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

What am I doing wrong? 我究竟做错了什么? I assume that if I can get the DataContext object to replace the = with is for null values, the deletes will work. 我认为,如果我能得到DataContext对象来代替=is空值时,会删除工作。 I don't know how to do that. 我不知道该怎么做。 I also assume this question has been asked before, but I can't find it. 我还假设之前已经问过这个问题,但我找不到它。

EDIT: I originally called my keys "primary" rather than "foreign". 编辑:我最初称我的键为“主要”而不是“外国”。 I meant to say "foreign". 我打算说“外国人”。 I edited my post to say "foreign" instead. 我编辑我的帖子说“外国”。 I am still having the same problem. 我仍然遇到同样的问题。

To make sure that you also catch nulls, you could modify your query to look like this : 为了确保您还捕获空值,您可以将查询修改为如下所示:

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

The main problem here - in SQL, nothing is equal to NULL. 这里的主要问题 - 在SQL中,没有任何东西等于NULL。 NULL is not equal even to itself! NULL甚至不等于它自己! "NULL = NULL" will evaluate to "false" in SQL query. 在SQL查询中,“NULL = NULL”将评估为“false”。 So, when you need to delete rows where [key2] == null, you need to write LINQ query which will produce SQL like 因此,当你需要删除[key2] == null的行时,你需要编写LINQ查询,它会产生类似SQL的

"WHERE [key2] = @p1 AND [key2] IS NULL" “WHERE [key2] = @ p1 AND [key2] IS NULL”

instead of 代替

"WHERE [key2] = @p1 AND [key2] = @p2". “WHERE [key2] = @ p1 AND [key2] = @ p2”。

How to do it? 怎么做? It seems the right way will be to compare [key2] with null. 似乎正确的方法是将[key2]与null进行比较。 For example, if you want to get all rows from tblSecurityMasterType where Name is NULL, this will be the wrong way: 例如,如果要从名称为NULL的tblSecurityMasterType获取所有行,则这将是错误的方式:

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

You will need to use this query instead: 您将需要使用此查询:

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

It's described here: http://smsohan.com/blog/2008/08/05/comparing-with-null-in-where-clause-in/ 它在这里描述: http//smsohan.com/blog/2008/08/05/comparing-with-null-in-where-clause-in/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM