假设我有这种情况:
Table Bar
Id int not null
Name string not null
和
Table Foo
Id int not nul
BarId int foreign key (Bar) references Id
当我尝试删除在Foo中有引用的Bar时,为什么EF会尝试将Foo设置BarId更新为NULL?
我有一个关于我的属性的验证,当有人试图将NULL设置为Bar时会引发,并且当EF尝试更新Foo时我收到此错误。
如果我尝试删除执行一个查询,例如“从foo中删除id = 1”,我得到:
The DELETE statement conflicted with the REFERENCE constraint "FooFK".
The conflict occurred in database "teste", table "dbo.Bar", column 'BarId'.
我想在使用EF时遇到此错误。有没有办法做到这一点? 我正在使用EF 4.3。
这是我的地图:
modelBuilder.Entity<Bar>().HasRequired(x => x.Foo).WithMany().Map(x => x.MapKey("FooId")).WillCascadeOnDelete(false);
答案 0 :(得分:0)
使用这两种方法可以“从数据库中删除项目”通常不正确。确切地说是这样的:
ObjectContext.DeleteObject(entity)在上下文中将实体标记为已删除。 (之后删除了EntityState。)如果之后调用SaveChanges,EF会向数据库发送SQL DELETE语句。如果违反了数据库中的引用约束,则将删除该实体,否则将引发异常。
EntityCollection.Remove(childEntity)将parent和childEntity之间的关系标记为已删除。如果从数据库中删除了childEntity本身,并且在调用SaveChanges时究竟发生了什么,取决于两者之间的关系类型:
如果关系是可选的,即从子级引用到数据库中的父级的外键允许NULL值,则此外部将设置为null,如果调用SaveChanges,则将为childEntity写入此NULL值数据库(即两者之间的关系被删除)。使用SQL UPDATE语句会发生这种情况。没有DELETE语句。
如果需要关系(FK不允许NULL值)且关系未识别(这意味着外键不是子(复合)主键的一部分),则必须添加子项到另一个父或你必须显式删除子(然后使用DeleteObject)。如果您不执行任何这些参数约束,则在调用SaveChanges时EF将抛出异常 - 臭名昭着的“由于一个或多个外键属性不可为空而无法更改关系”异常或类似的。
如果关系正在识别(因为主键的任何部分都不能为NULL,则必然需要),EF也会将childEntity标记为已删除。如果调用SaveChanges,则会将SQL DELETE语句发送到数据库。如果数据库中没有违反其他参照约束,则将删除该实体,否则将引发异常。
我实际上对您链接的MSDN页面上的“备注”部分感到困惑,因为它说:“如果关系具有参照完整性约束,则在依赖对象上调用Remove方法会标记关系和依赖对象删除。“这对我来说似乎是不准确甚至是错误的,因为上面的所有三种情况都有“参照完整性约束”,但只有在最后一种情况下才会删除子。 (除非它们与“依赖对象”意味着一个参与识别关系的对象,但这可能是一个不寻常的术语。)