实体框架级联删除 [英] Entity Framework Cascading Delete

查看:66
本文介绍了实体框架级联删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,很抱歉,如果我在这里缺少一些基本的内容,但是我是EF的新手,并且仍然想尽办法先设置DB代码....

我遇到与此,但似乎无法从注释中解决我需要对特定模型进行的处理。当我在添加个公共虚拟Actor actor之后尝试更新数据库时,{组; } 到我的UseCase类,出现以下错误:

I'm having a similar problem to this Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths but can't seem to work out from the comments there what I need to do with my particular model. When I attempt to update database after adding in public virtual Actor actor { get; set; } to my UseCase class, I get this error:

Introducing FOREIGN KEY constraint 'FK_dbo.UseCase_dbo.Actor_ActorID' on table 'UseCase' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.

我知道这一定与我的FK约束的设置方式有关(可能是某些原因)与删除用例有关,这意味着我最终将从多个其他表中删除数据)。

I know it must be something to do with the way that my FK constraints are set up (probably something to do with deleting a use case meaning that I'll end up deleting data from multiple other tables).

我尝试关闭级联删除,但仍然收到错误:

I tried turning off cascading delete, but still get the error:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //prevent table names created by entity framework being pluralised
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            //Turn off delete cascades between parent child tables. May need to put this back in future, but for the time being it is stopping the database being updated through the package manager console (error is that a foregin key constraint may cause cycles or multiple cascade paths) 
            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
            modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
        }

这是我的模型。应该发生的是,只有删除了一个项目,才应该删除其用例或参与者。使用案例时,不应删除Actor,因为它们可能涉及其他UseCases。谁能指出我需要改变的地方?

Here are my models. What should happen is that only if a project is deleted should it's use cases or actors be deleted. Actors should not be deleted when a UseCase is, because they may be involved in other UseCases. Can anyone point to what I need to change?

最后,正确的模型确实是此 Project>演员>用例。我假设我应该删除 public virtual int ProjectID {get;组; } 公共虚拟项目项目{get;组; }

Finally, the correct model indeed is this Project > Actors > Use Cases. I assume that I should just remove public virtual int ProjectID { get; set; } and public virtual Project project { get; set; } from UseCase?

学习很痛苦!

 public class Project
    {
        public virtual int ID {get; set;}
        [DisplayName ("Project Name")]
        public virtual string ProjectName { get; set; }
        [DisplayName("Client")]    
        public virtual string ClientID { get; set; }
        public virtual string Description { get; set; }
        [DisplayName("Use Cases")]
        public virtual ICollection <UseCase> UseCases { get; set; } 

   }

public class UseCase

{
    public virtual int ID { get; set; }
    [Required]
    public virtual int ProjectID { get; set; }
    public virtual int ActorID { get; set; }
    [Required]
    public virtual Actor actor { get; set; }
    public virtual string Title { get; set; }
    public virtual Level? Level { get; set; }
    public virtual string Precondition { get; set; }
    public virtual string MinimalGuarantee { get; set; }
    public virtual string SuccessGuarantee { get; set; }
    public virtual ICollection<Step> Steps { get; set; }
    public virtual ICollection<Extension> Extensions { get; set; }
    public virtual ICollection<Query> Queries { get; set; }

}

public class Actor
{
    public virtual int ID { get; set; }
    public virtual int projectID { get; set; }
    public virtual Project project { get; set; } 
    public virtual string Title { get; set; }

    [DataType(DataType.MultilineText)]
    public virtual string Description { get; set; }

}

已更新是我根据以下反馈修改的代码。无论是运行应用程序并尝试创建数据库,还是尝试通过包管理器 Update-Database 更新数据库时,我仍然遇到相同的错误。快把我逼疯了。

UPDATED So, here is my modified code based on feedback below. I'm still getting the same error, either when I run the application and it tries to create the DB or when I try to update the database through package manager Update-Database. Driving me crazy.

对我来说,以下代码表示如果我删除一个参与者,也要删除该参与者的用例。如果删除项目,则删除该项目的参与者,因此也删除每个参与者的用例。但是,如果我删除一个项目,请不要删除用例。显然,我误会很严重:-(

To me, the code below says if I delete an actor, delete the use cases for that actor too. If I delete a project, delete the actors for the project and therefore delete the use cases for each actor too. But if I delete a project, don't delete the use cases. Clearly, I'm misunderstanding something quite badly :-(

    modelBuilder.Entity<Actor>()
    .HasMany(a => a.useCases)
    .WithRequired(uc => uc.actor)
    .HasForeignKey(uc => uc.ActorID)
    .WillCascadeOnDelete(true); // and this works

    modelBuilder.Entity<Project>()
    .HasMany(p => p.actors)
    .WithRequired(a => a.project)
    .HasForeignKey(a => a.projectID)
    .WillCascadeOnDelete(true); // this works

    modelBuilder.Entity<Project>()
    .HasMany(p => p.UseCases)
    .WithRequired(uc => uc.project)
    .HasForeignKey(uc => uc.ProjectID)
    .WillCascadeOnDelete(false); // disable this cascading delete


推荐答案

您需要禁用层叠在您的情况下,您具有以下路径:

You need to disable cascade deletes for all but one of the possible paths. In your case you have the following paths:

Project -> UseCase
Project -> Actor -> UseCase

您可以允许单个路径级联删除 UseCase -通过 Project 实体或 Actor 实体。但是,如果我们在 Project -> UseCase 路径中禁用级联删除,我们仍将通过以下方式实现级联删除演员

You can allow a single path for cascading deletion of UseCase - via the Project entity or Actor entity. However, if we disable cascading deletes in the Project -> UseCase path, we'll still achieve a cascading delete via Actor:

modelBuilder.Entity<Project>()
    .HasMany( p => p.UseCases )
    .WithRequired( uc => uc.Project )
    .HasForeignKey( uc => uc.ProjectID )
    .WillCascadeOnDelete( false ); // disable this cascading delete

modelBuilder.Entity<Project>()
    .HasMany( p => p.Actors )
    .WithRequired( a => a.Project )
    .HasForeignKey( a => a.ProjectID )
    .WillCascadeOnDelete( true ); // this works

modelBuilder.Entity<Actor>()
    .HasMany( a => a.UseCases )
    .WithRequired( uc => uc.Actor )
    .HasForeignKey( uc => uc.ActorID )
    .WillCascadeOnDelete( true ); // and this works

侧面注释:

您的模型存在数据不一致的危险- Actor UseCase 的FK均通过 ProjectID 进行项目,但是模型中没有任何内容可以强制执行由 Actor 引用的一个 UseCase 具有相同的 ProjectID -一个 Actor 来自项目2中的 UseCase 可以引用项目1。您可以将 ProjectID 包含在 Actor PK中,然后包含在 UseCase -> Actor FK,确保 UseCase引用的 Actor 属于同一个 Project ,但这从技术上讲违反了 2NF

Your model has a data inconsistency hazard - both Actor and UseCase have a FK to Project via ProjectID, but there is nothing in the model to enforce the Actor referenced by a UseCase has the same ProjectID - an Actor from "Project 1" could be reference by a UseCase from "Project 2". You could include the ProjectID in the Actor PK and then in the UseCase->Actor FK, ensuring that the Actor referenced by a UseCase belongs to the same Project, but this would technically violate the 2NF.

正确模型可能是项目-> 演员-> UseCases 层次结构,只需要您通过 Actors 加入即可获得项目 UseCase s

The 'proper' model is probably a Project->Actors->UseCases hierarchy, simply requiring you to join through Actors to get a Project's UseCases

这篇关于实体框架级联删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆