【发布时间】:2016-01-24 13:22:22
【问题描述】:
我有一个线程,其中包含作为线程内容的一部分的 startpost。它还包括一个回复列表,这些回复也是帖子。
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;}
}
创建线程后,我只需将它们添加到 DbContext 并保存即可。这没有问题。但是如果提交了回复,我会将它们添加到帖子列表中,并将线程的实体标记为这样修改
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();
这是我在 Thread.FirstPost 上违反外键的问题:
无法添加或更新子行:外键约束失败 ("MyTable"."posts", CONSTRAINT "Thread_FirstPost" FOREIGN KEY ("Id") REFERENCES "threads" ("Id") ON DELETE NO ACTION ON更新无操作)
我找到了很多关于此的信息。简而言之,所有人都说,这与 EF 检查完整性的默认行为有关。因此,当必须删除线程时,它取决于也必须删除的 FirstPost,但这取决于似乎使 EF 感到困惑的线程。
对于这个问题,互联网有 2 个解决方案:使用 fluent-API 禁用使用 .WillCascadeOnDelete(false); 的实体的级联或通过删除约定完全禁用它。我尝试了两种方法:
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);
}
但是没有任何效果,我得到了与以前相同的异常。我不知道为什么,似乎所有其他有这个问题的人都可以通过使用其中一种方法来解决它,但就我而言,两者都没有效果......
来自 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
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)
以下是我在研究该主题时发现的一些页面: http://weblogs.asp.net/manavi/associations-in-ef-code-first-ctp5-part-3-one-to-one-foreign-key-associations
http://www.codeproject.com/Articles/368164/EF-Data-Annotations-and-Code-Fluent
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
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
Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?
Entity Framework: how to solve "FOREIGN KEY constraint may cause cycles or multiple cascade paths"?
【问题讨论】:
-
它说 FOREIGN KEY 约束失败,它与删除时的级联无关。当您向数据库添加条目时,您只需确保所有 FK 都与它们所引用的导航属性上的键匹配(即使它们稍后被更改,它们也必须设置为相同的临时值)跨度>
-
我编辑了一些我在研究过程中发现的页面来解决这个错误。我认为这里的重点是更新而不是删除,因为我不删除数据,我更新线程。 FK 很好,在创建线程 EF 后使用 Id 1 正确加载 FirstPost。这就是我无法理解此错误的原因 - 我认为我必须指定更新操作而不是 NO ACTION,但是我不知道该怎么做。
-
我认为它只是提到了插入失败的完整约束。
-
在线程类中,尝试在
public virtual Post FirstPost{get;set;}上方添加[ForeignKey("FirstPostId")],您需要为此使用using System.ComponentModel.DataAnnotations; -
这给了我在后模型中找不到 FK 的错误。我认为它应该是 [ForeignKey("FirstPost")] 并高于 FirstPostId 属性,但这不起作用。 @DevilSuichiro 抱歉,我完全听不懂你想说什么。
标签: c# database entity-framework asp.net-mvc-5