简体   繁体   English

ASP.NET MVC 5 EF无法添加或更新子行:外键约束失败

[英]ASP.NET MVC 5 EF Cannot add or update a child row: a foreign key constraint fails

I've a thread which contains a startpost as part of the thread-content. 我有一个线程,其中包含一个startpost作为线程内容的一部分。 It also includes a list of replys, which are also posts. 它还包括回复列表,这些列表也是帖子。

class Post {
    [Key]
    public int Id{get;set;}
    public DateTime CreationDate{get;set;}
    public virtual string Content{get;set;}
    public int ThreadId{get;set;}
    public virtual Thread Thread{get;set;}
}

class Thread {
    [Key]
    public int Id{get;set;}
    public string Title{get;set;}
    public int FirstPostId{get;set;}
    public virtual Post FirstPost{get;set;}
    public List<Post> Replys{get;set;}
}

When a thread is created i simply add them to the DbContext and save it. 创建线程后,我只需将它们添加到DbContext并保存。 This works without issues. 这没有问题。 But if a reply is submitted, I add them to the post-list and mark the entity of the thread as modified like this 但是,如果提交了答复,则将其添加到帖子列表中,并将线程的实体标记为已修改,如下所示

var db = new MyContext();
var thread = db.Threads.Where(thread => thread.Id = threadId).FirstOrDefault();
thread.Replys.Add(newPost);
db.Entry<Thread>(thread).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();

Here is the problem that I get a violation of the foreignkey on Thread.FirstPost: 这是我在Thread.FirstPost上违反外键的问题:

Cannot add or update a child row: a foreign key constraint fails ("MyTable"."posts", CONSTRAINT "Thread_FirstPost" FOREIGN KEY ("Id") REFERENCES "threads" ("Id") ON DELETE NO ACTION ON UPDATE NO ACTION) 无法添加或更新子行:外键约束失败(“ MyTable”。“ posts”,CONSTRAINT“ Thread_FirstPost”外键(“ Id”)参考“线程”(“ Id”)删除无操作更新无操作)

I found many information about this. 我发现了许多有关此的信息。 In short, all say, that this is related to the default behavior of EF that checks the integrity. 简而言之,这与EF检查完整性的默认行为有关。 So when a Thread has to be deleted it depends on the FirstPost which has also to be deleted but this depends on the Thread which seem to confuse EF. 因此,当必须删除线程时,它取决于还必须删除的FirstPost,但这取决于似乎使EF混淆的线程。

The internet has 2 solutions for this problem: Using fluent-API to disable cascade for the entity using .WillCascadeOnDelete(false); 互联网针对此问题提供了两种解决方案:使用fluent-API使用.WillCascadeOnDelete(false);禁用实体的级联.WillCascadeOnDelete(false); or disable it completely by removing the convention. 或通过删除约定将其完全禁用。 I tried both ways: 我尝试了两种方式:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        //base.OnModelCreating(modelBuilder);
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        modelBuilder.Entity<Thread>()
            .HasOptional(t => t.FirstPost)
            .WithRequired()
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Post>()
            .HasOptional(p => p.Thread)
            .WithMany()
            .HasForeignKey(p => p.ThreadId)
            .WillCascadeOnDelete(false);
}

But nothing is working, I get the same exception than before. 但是没有任何效果,我得到了比以前相同的例外。 I have no idea why, and it seems that all others which had this problem could solve it by using one of those methods, but in my case both have no effect... 我不知道为什么,似乎所有其他有此问题的人都可以使用其中一种方法来解决它,但就我而言,这两种方法都无效。

Table-Definitions from Visual Studio Server-Explorer Visual Studio Server-Explorer中的表定义

CREATE TABLE `posts` (
  `Id` int(11) NOT NULL,
  `CreationDate` datetime NOT NULL,
  `Content` longtext NOT NULL,
  `ThreadId` int(11) NOT NULL,
  PRIMARY KEY (`Id`),
  KEY `ThreadId` (`ThreadId`),
  CONSTRAINT `Thread_Post` FOREIGN KEY (`Id`) REFERENCES `threads` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `Thread_Replys` FOREIGN KEY (`ThreadId`) REFERENCES `threads` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1

CREATE TABLE `threads` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Title` longtext NOT NULL,
  `PostId` int(11) NOT NULL,
  `ViewsCount` int(11) NOT NULL,
  `IsClosed` tinyint(1) NOT NULL,
  `IsVisible` tinyint(1) NOT NULL,
  `ReplysCount` int(11) NOT NULL,
  PRIMARY KEY (`Id`),
  UNIQUE KEY `Id` (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Table-Definition generated by EF (from Database-Server) EF生成的表定义(来自数据库服务器)

CREATE TABLE `Posts`(
    `Id` int NOT NULL, 
    `CreationDate` datetime NOT NULL, 
    `Content` longtext NOT NULL, 
    `ThreadId` int NOT NULL
)
ALTER TABLE `Posts` ADD PRIMARY KEY (Id)
ALTER TABLE `Posts` ADD CONSTRAINT Thread_Post
ALTER TABLE `Posts` ADD KEY (`ThreadId`)
ALTER TABLE `Posts` ADD CONSTRAINT Thread_Replys
ALTER TABLE `Posts` ADD CONSTRAINT Thread_Post
    FOREIGN KEY (Id)
    REFERENCES `Threads` (Id)
ALTER TABLE `Posts` ADD CONSTRAINT Thread_Replys
    FOREIGN KEY (ThreadId)
    REFERENCES `Threads` (Id)
ALTER TABLE `Posts` ADD CONSTRAINT Thread_Replys
    FOREIGN KEY (ThreadId)
    REFERENCES `Threads` (Id)
    ON DELETE NO ACTION ON UPDATE NO ACTION

CREATE TABLE `Threads`(
    `Id` int NOT NULL AUTO_INCREMENT UNIQUE, 
    `Title` longtext NOT NULL, 
    `PostId` int NOT NULL, 
    `ViewsCount` int NOT NULL, 
    `IsClosed` bool NOT NULL, 
    `IsVisible` bool NOT NULL, 
    `ReplysCount` int NOT NULL
)
ALTER TABLE `Threads` ADD PRIMARY KEY (Id)

Here are some pages I found on my research to this topic: http://weblogs.asp.net/manavi/associations-in-ef-code-first-ctp5-part-3-one-to-one-foreign-key-associations 这是我在研究此主题时发现的一些页面: http : //weblogs.asp.net/manavi/associations-in-ef-code-first-ctp5-part-3-one-to-one-foreign-key -协会

http://www.codeproject.com/Articles/368164/EF-Data-Annotations-and-Code-Fluent http://www.codeproject.com/Articles/368164/EF-Data-Annotations-and-Code-Fluent

http://geekswithblogs.net/danemorgridge/archive/2010/12/17/ef4-cpt5-code-first-remove-cascading-deletes.aspx http://geekswithblogs.net/danemorgridge/archive/2010/12/17/ef4-cpt5-code-first-remove-cascading-deletes.aspx

http://patrickdesjardins.com/blog/entity-framework-4-3-delete-cascade-with-code-first-poco http://patrickdesjardins.com/blog/entity-framework-4-3-delete-cascade-with-code-first-poco

ASP.NET MVC 4 Multiple Foreign Keys Referencing Single Parent Entity ASP.NET MVC 4引用单个父实体的多个外键

http://www.davepaquette.com/archive/2012/09/15/whered-my-data-go-andor-how-do-i-get-rid-of-it.aspx http://www.davepaquette.com/archive/2012/09/15/whered-my-data-go-andor-how-do-i-get-rid-of-it.aspx

http://czetsuya-tech.blogspot.de/2012/01/specify-on-delete-no-action-or-on.html#.Viy-0X54u9J http://czetsuya-tech.blogspot.de/2012/01/specify-on-delete-no-action-or-on.html#.Viy-0X54u9J

Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why? 引入FOREIGN KEY约束可能会导致循环或多个级联路径-为什么?

Entity Framework: how to solve "FOREIGN KEY constraint may cause cycles or multiple cascade paths"? 实体框架:如何解决“ FOREIGN KEY约束可能导致循环或多个级联路径”?

Specify ON DELETE NO ACTION in ASP.NET MVC 4 C# Code First 在ASP.NET MVC 4 C#代码中首先指定ON DELETE NO ACTION

Your foreign keys are not set properly, it's ok not to define a foreign key explicitly in case you user the original class name, I'll explain it on your code: 您的外键设置不正确,最好不要显式定义外键,以防您使用原始类名,我将在代码中进行解释:

class Post {
    [Key]
    public int Id{get;set;}
    public DateTime CreationDate{get;set;}
    public virtual string Content{get;set;}
    public int ThreadId{get;set;}  **-> here you used ThreadId which is implicitly a foreignkey for Thread, and that's good**
    public virtual Thread Thread{get;set;}
}

class Thread {
    [Key]
    public int Id{get;set;}
    public string Title{get;set;}
    public int FirstPostId{get;set;} **-> here you can do the same by changing this to PostId**
    public virtual Post FirstPost{get;set;} **-> and this to Post**
    public List<Post> Replys{get;set;}
}

Or you have a better option of using data annotations: 或者,您可以使用数据注释的更好的选择:

Replace this: 替换为:

 public virtual Post FirstPost{get;set;}

with this: 有了这个:

[ForeignKey("FirstPostId")]
public virtual Post FirstPost{get;set;}

This is telling EF that FirstPostId is the foreignkey for `FirstPost. 这告诉EF FirstPostId是`FirstPost的外键。

Let me know if that worked. 让我知道是否可行。

UPDATE 更新

I've changed your sql code manually and it works now: 我已经手动更改了您的sql代码,现在可以使用:

CREATE TABLE threads (
  Id int NOT NULL,
  Title nvarchar(max) NOT NULL,
  PostId int,
  ViewsCount int NOT NULL,
  IsClosed tinyint NOT NULL,
  IsVisible tinyint NOT NULL,
  ReplysCount int NOT NULL,
  PRIMARY KEY (Id),
) 

CREATE TABLE posts (
  Id int NOT NULL,
  CreationDate datetime NOT NULL,
  Content nvarchar(max) NOT NULL,
  ThreadId int NOT NULL,
  PRIMARY KEY (Id),
  CONSTRAINT Thread_Post FOREIGN KEY (Id) REFERENCES threads (Id) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT Thread_Replys FOREIGN KEY (ThreadId) REFERENCES threads (Id) ON DELETE NO ACTION ON UPDATE NO ACTION
)

ALTER TABLE threads ADD CONSTRAINT Post_Thread FOREIGN KEY (PostId) REFERENCES posts (Id) ON DELETE NO ACTION ON UPDATE NO ACTION

You can't define thread to require postID, and post to require threadID at the same time, if you do you won't be able to create either (unless you create both at the same time - meaning in the same db.savechanges()). 您不能将线程定义为需要postID,也不能同时定义为post来要求threadID,如果那样的话,您将无法创建两者(除非您同时创建两者-意味着在同一个db.savechanges( ))。

Think about it. 想一想。 you want to define a thread using a post that doesn't exists yet. 您想使用尚不存在的帖子来定义线程。

The root problem is that your model contains a 1:1 association between Post and Thread in which Thread is the principle, or independent, entity. 根本问题是您的模型在PostThread之间包含1:1关联,其中Thread是主要实体或独立实体。 This is expressed by the part ... 这由...部分表示

modelBuilder.Entity<Thread>()
    .HasOptional(t => t.FirstPost)
    .WithRequired()

You see it reflected in the DDL statement ... 您会看到它反映在DDL语句中...

ALTER TABLE `Posts` ADD CONSTRAINT Thread_Post
    FOREIGN KEY (Id)
    REFERENCES `Threads` (Id)

So Post's primary key is also a foreign key to Thread . 因此, Post's主键也是 Thread的外键。 This means that you can't ever insert more than one Post per Thread ! 这意味着每个Thread最多只能插入一个Post (Because each subsequent Post necessarily should have a new PK value, but that doesn't refer to an existing Thread so you get constraint violations). (因为每个后续的Post必须具有一个新的PK值,但这并不引用现有的Thread因此您会遇到约束违规的情况)。

You could solve this (maybe) by making Post the principle entity. 您可以(使)以Post为主体来解决此问题。 In that case, Thread would have a PK/FK combination referring to its first Post . 在这种情况下, Thread将具有引用其第一个Post的PK / FK组合。 However, to me, 1:1 associations convey that entities are strongly related to a point where they're almost one ( Student - StudentDetails ). 但是,对我而言,1:1关联表示实体与它们几乎是一个实体的点密切相关( Student - StudentDetails )。 So I don't think a 1:1 association is appropriate here anyway. 因此,我认为1:1关联并不适合。

I would suggest this mapping: 我建议这种映射:

modelBuilder.Entity<Thread>()
    .HasOptional(t => t.FirstPost)
    .WithMany()
    .HasForeignKey(t => t.FirstPostId)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<Post>()
    .HasRequired(p => p.Thread)
    .WithMany(t => t.Replies)
    .HasForeignKey(p => p.ThreadId)
    .WillCascadeOnDelete(false);

This theoretically turns the relationship between Thread and FirstPost into 1-to-many, but practically it means that Thread now has a foreign key to its first post, and these complicated PK/FK combinations are gone. 从理论上讲,这将ThreadFirstPost之间的关系变成一对多,但实际上这意味着Thread现在具有其第一个帖子的外键,并且这些复杂的PK / FK组合也消失了。 Note that FirstPostId should be a nullable int to support this. 请注意, FirstPostId应为可为null的int来支持此功能。

On the other hand, if in your opinion a Thread and its first post are closely related you could consider merging both into a thread that also has the attributes of its first post ( CreationDate , Content ). 在另一方面,如果在您看来,一个Thread和它的第一篇文章密切相关的,你可以考虑合并双方进入一个线程,也有它的第一篇文章(属性CreationDateContent )。 You'll end up with a very simple model of threads (posts?) with replies in which still nothing is redundant. 最后,您将获得一个非常简单的线程模型(帖子?),其中包含答复,但仍然没有多余的内容。

暂无
暂无

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

相关问题 ASP.NET:无法添加或更新子行:外键约束失败 - ASP.NET: Cannot add or update child row: a foreign key constraint fails EF6代码优先:MySqlException:无法添加或更新子行:外键约束失败 - EF6 Code First: MySqlException: Cannot add or update a child row: a foreign key constraint fails 无法添加或更新子行:外键约束失败 - Cannot add or update a child row: a foreign key constraint fails “无法添加或更新子行:外键约束失败”错误 - 'Cannot add or update a child row: a foreign key constraint fails' Error 错误-无法添加或更新子行:外键约束失败 - Error - Cannot add or update a child row: a foreign key constraint fails 无法添加或更新子行:在 foreach 中执行 INSERT 时外键约束失败 - Cannot add or update a child row: a foreign key constraint fails while doing INSERT in a foreach C# - 无法添加或更新子行:外键约束失败 - C# - Cannot add or update a child row: a foreign key constraint fails UPDATE语句与asp.net mvc 5中的FOREIGN KEY约束冲突 - The UPDATE statement conflicted with the FOREIGN KEY constraint in asp.net mvc 5 无法删除或更新父行:外键约束失败 - Cannot delete or update a parent row: a foreign key constraint fails C#:在数据库中添加对象时,出现“ MySqlException:无法添加或更新子行:外键约束失败” - C#: I'm getting a “MySqlException: Cannot add or update a child row: a foreign key constraint fails” when i am Adding an object in my database
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM