Entity Framework 6.0 - 删除时的奇怪行为
Posted
技术标签:
【中文标题】Entity Framework 6.0 - 删除时的奇怪行为【英文标题】:Entity Framework 6.0 - Strange behaviour on delete 【发布时间】:2015-01-03 12:24:09 【问题描述】:我决定第一次使用 Entity Framework 6.0。所以是的,我对此很陌生。 与往常一样,我首先创建了数据库,然后生成了 Code First 模型(通过 Visual Studio 向导),如下所示:
Partial Public Class DataContext
Inherits DbContext
Public Sub New()
MyBase.New("name=DataContext")
End Sub
Shared Sub New()
DbInterception.Add(New FullTextInterceptor())
End Sub
Public Overridable Property StatusInfoes As DbSet(Of StatusInfo)
Public Overridable Property UpdateSets As DbSet(Of UpdateSet)
Public Overridable Property Users As DbSet(Of User)
Protected Overrides Sub OnModelCreating(ByVal modelBuilder As DbModelBuilder)
modelBuilder.Configurations.Add(New UpdateSetFtsMap)
modelBuilder.Entity(Of StatusInfo)() _
.Property(Function(e) e.Information) _
.IsUnicode(False)
modelBuilder.Entity(Of UpdateSet)() _
.Property(Function(e) e.Title) _
.IsUnicode(False)
modelBuilder.Entity(Of UpdateSet)() _
.Property(Function(e) e.Files) _
.IsUnicode(False)
modelBuilder.Entity(Of UpdateSet)() _
.HasMany(Function(e) e.StatusInfoes) _
.WithRequired(Function(e) e.UpdateSet) _
.WillCascadeOnDelete(False)
modelBuilder.Entity(Of User)() _
.Property(Function(e) e.Login) _
.IsUnicode(False)
modelBuilder.Entity(Of User)() _
.Property(Function(e) e.Password) _
.IsUnicode(False)
modelBuilder.Entity(Of User)() _
.Property(Function(e) e.Surname) _
.IsUnicode(False)
modelBuilder.Entity(Of User)() _
.Property(Function(e) e.Name) _
.IsUnicode(False)
modelBuilder.Entity(Of User)() _
.HasMany(Function(e) e.StatusInfoes) _
.WithRequired(Function(e) e.User) _
.WillCascadeOnDelete(False)
End Sub
Public Function GetServerDate() As DateTime
Return Database.SqlQuery(Of DateTime)("Select GetDate()").SingleOrDefault
End Function
End Class
所以我有一个 UpdateSet 对象,其中至少有一个 StatusInfo 对象。 到目前为止一切顺利。
奇怪的是删除。这是我的代码:
Public Function DeleteById(id As Integer) As Integer Implements IDataMapper(Of UpdateSetDataTransferObject).DeleteById
Dim result = -1
Using ctx As New DataContext
Dim dbUpdateSet = (From o In ctx.UpdateSets Where o.Id = id Select o).SingleOrDefault
If dbUpdateSet IsNot Nothing Then
ctx.UpdateSets.Remove(dbUpdateSet)
Try
ctx.SaveChanges()
result = 0
Catch ex As DbUpdateException
End Try
End If
End Using
Return result
End Function
奇怪的是,有时它会起作用。 (假设 20 个中有 1 个)。 通过调试,我观察到大多数情况下的代码
ctx.UpdateSets.Remove(dbUpdateSet)
从 StatusInfoes 集合中删除所有 StatusInfo 对象(子对象),因此我认为 EF 没有有关要删除的子对象的信息。所以我得到了错误:
DELETE 语句与 REFERENCE 约束“FK_UpdateSetStatus_UpdateSet”冲突。冲突发生在数据库“UpdateWizard”、表“dbo.StatusInfo”、列“UpdateSetId”中。 声明已终止。
正如我之前提到的,有时它会起作用。那些时候,StatusInfo 对象的集合没有被 remove 命令清除。
谁能帮忙?
【问题讨论】:
【参考方案1】:您收到此错误的原因
DELETE 语句与 REFERENCE 约束“FK_UpdateSetStatus_UpdateSet”冲突。冲突发生在数据库“UpdateWizard”、表“dbo.StatusInfo”、列“UpdateSetId”中。
在我看来,这不是 EF 错误,它来自 sql 服务器的错误,因为您有外键约束,这意味着您无法删除记录,因为其他记录依赖于它。
【讨论】:
@shadow 在删除 UpdateSet 之前,您必须删除所有具有给定 UpdateSetId 的 StatusInfo 条目。 感谢您的宝贵时间。我知道它来自 SQL Server,但我不明白为什么在某些情况下工作正常而在其他情况下却不行。 @dckuehn 我认为这是 EF 的工作。我不想相信我们必须为每一个亲子关系都这样做。对我来说,问题出现在 ctx.UpdateSets.Remove(dbUpdateSet) 语句中。不知何故,信息丢失了。 很抱歉,我无法提供更多帮助。我工作的公司不相信硬删除任何数据,我们在任何需要的地方设置Deleted=True
布尔值,所以我不熟悉删除数据,尽管我确实经常使用EF。搜索“级联删除”,它可能会让你更接近你所需要的。
出现错误时您是否可以访问数据库,针对 DATABASE 运行该 SQL 代码,如果它直接在 sql 上显示错误,请将其显示给您的公司
@coldTold:是国内的本地项目(矿山项目)。只是尝试 EF 6.0 我的猜测是 Fluent API 代码中缺少一些东西。我觉得奇怪的是,当我从它的 dBSet 中删除一个父对象时,remove 命令会清除子集合。之后出现错误是合乎逻辑的,因为没有信息让 EF 先删除子行,然后再删除父行。它尝试仅删除数据库中约束不允许的父级。仍在搜索中。再次感谢。【参考方案2】:
我找到了解决方案,现在看起来很明显。我只需要在父级(UpdateSet 对象)和子级(StatusInfo 对象)之间的外键约束上启用级联删除。在阅读一篇关于在 EF4.0 中修改实体的文章时,我遇到了一段说“在数据库和 EF 配置中打开或关闭级联删除”的段落。就我而言,因为首先创建了数据库,所以它关闭了,所以当我创建模型(代码优先)时,它在 EF 中也关闭了。所以我想在这种情况下我不得不手动删除所有孩子。老实说,因为我是老派,我对此并不感到兴奋(在约束下级联删除),但我无法想象 EF 有其他方式来做到这一点。所以再次感谢大家。希望这对其他人有帮助。
【讨论】:
以上是关于Entity Framework 6.0 - 删除时的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章
Entity Framework Core 6.0 预览4 性能改进
Entity Framework 6.0 Raw Sql 查看模型
Entity Framework Core 6.0 中的新功能介绍
Entity Framework Core 6.0 中的新功能介绍