实体框架:为什么忽略WillCascadeOnDelete()方法?

abz*_*rak 13 c# entity-framework cascade one-to-many

这是我的情况:

public abstract class Article
{
    [key]
    public Guid Guid { get; set;}

    public string Name { get; set;}
    .
    .
    .
}

public class Download : Article
{
    ...
}

public abstract class Category : Article
{
    ...
}

public class DownloadCategory : Category 
{
    ....
}
Run Code Online (Sandbox Code Playgroud)

然后我应该在下载之间有一个多对多的关系,DownloadCategory就像这样:

public class DownloadInCategory
{
    [Key, Column(Order = 1), Required]
    [ForeignKey("Download")]
    Public Guid DownloadGuid { get; set; }

    Public Download Download { get; set; }

    [Key, Column(Order = 2), Required]
    [ForeignKey("Category")]
    Public Guid CategoryGuid { get; set; }

    Public DownloadCategory Category { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当我Add-MigrationDownloadInCategory实体调用创建的迁移时:

CreateTable("dbo.DownloadInCategories",
c => new
{
    CategoryGuid = c.Guid(nullable: false),
    DownloadGuid = c.Guid(nullable: false),
})
.PrimaryKey(t => new { t.CategoryGuid, t.DownloadGuid })
.ForeignKey("dbo.DownloadCategories", t => t.CategoryGuid)
.ForeignKey("dbo.Downloads", t => t.DownloadGuid, cascadeDelete: true)
.Index(t => t.CategoryGuid)
.Index(t => t.DownloadGuid);
Run Code Online (Sandbox Code Playgroud)

这是我的问题:你注意到它没有添加cascadeDelete: true到一个外键.为什么!!!!!!?????

我应该提一下,我没有改变任何modelbuilder公约.所以这个模式应该在迁移中删除Casscade.我的属性是[Required].

我究竟做错了什么?

多谢你们...

更新: 请注意,课程ArticleCategory课程abstract.我改变了上面的课程

更新2: 此架构没有逻辑问题.如果我手动编辑迁移,它将正常更新数据库.

更新3: 我的EF继承方法是TPC

更新4: 经过一些调查和测试似乎问题是继承的Category.何时DownloadCategory继承Category,未部署Cascade.但是当我DownloadCategory直接从Article 继承时,会部署Cascade.但为什么又一次?

Pau*_*ill 3

我想这是因为:

DownloadCategory : Category : Article
Run Code Online (Sandbox Code Playgroud)

Download : Article
Run Code Online (Sandbox Code Playgroud)

关键在于 Article 类。多个DownloadCategories可以使用相同的Category,因此它不会级联删除,因为这可能会导致其他DownloadCategory的损坏。

这可能是实体框架的故障,因为您正在使用 TPC,所以应该推断出这一点。请查看这篇文章以获取解决方法。

具体来说这些部分:

在大多数情况下,实体框架可以推断哪个类型是依赖关系,哪个类型是关系中的主体。但是,当关系的两端都是必需的或者两端都是可选的时,实体框架无法识别依赖关系和主体。当需要关系的两端时,请在该方法之后使用WithRequiredPrincipal or 。当关系的两端都是可选的时,请在该方法之后使用or 。WithRequiredDependentHasRequiredWithOptionalPrincipalWithOptionalDependentHasOptional

// Configure the primary key for the OfficeAssignment 
modelBuilder.Entity<OfficeAssignment>() 
    .HasKey(t => t.InstructorID); 

modelBuilder.Entity<Instructor>() 
    .HasRequired(t => t.OfficeAssignment) 
    .WithRequiredPrincipal(t => t.Instructor);
Run Code Online (Sandbox Code Playgroud)

您可以通过该 WillCascadeOnDelete方法对关系进行级联删除。如果依赖实体上的外键不可为空,则 Code First 会在关系上设置级联删除。如果依赖实体上的外键可为空,则 Code First 不会对关系设置级联删除,并且当删除主体时,外键将设置为null

您可以使用以下方法删除这些级联删除约定:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>()
Run Code Online (Sandbox Code Playgroud)

以下代码配置所需的关系,然后 禁用级联删除。

modelBuilder.Entity<Course>() 
    .HasRequired(t => t.Department) 
    .WithMany(t => t.Courses) 
    .HasForeignKey(d => d.DepartmentID) 
    .WillCascadeOnDelete(false);
Run Code Online (Sandbox Code Playgroud)

  • 一对一关系项只是为了说明 EF 的推断存在局限性。我不认为它无关紧要,但请随意编辑答案以删除令人困惑的内容。这个问题最初似乎是在问为什么 EF 不自动推断级联。然后你提到了抽象和 TPC,所以我推断你想要一个解决方法。那么问题是通过解决方法部署迁移吗?这是 3 个独立的问题。所有更新意味着这个问题对其他人来说很难阅读。您能否在考虑到所有这些的情况下重写问题? (2认同)