Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET MVC 5 EF无法添加或更新子行:外键约束失败_C#_Database_Entity Framework_Asp.net Mvc 5 - Fatal编程技术网

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

C# ASP.NET MVC 5 EF无法添加或更新子行:外键约束失败,c#,database,entity-framework,asp.net-mvc-5,C#,Database,Entity Framework,Asp.net Mvc 5,我有一个包含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

我有一个包含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;}
}
但是什么都没用,我得到了和以前一样的例外。我不知道为什么,似乎所有其他有这个问题的人都可以用这些方法中的一种来解决它,但在我的情况下,这两种方法都没有效果

Visual Studio服务器资源管理器中的表定义

EF从数据库服务器生成的表定义

以下是我在这个主题的研究中发现的一些页面:


您的外键设置不正确,如果您使用原始类名,则可以不显式定义外键,我将在代码中解释:

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;}
}
为此:

[ForeignKey("FirstPostId")]
public virtual Post FirstPost{get;set;}
这是告诉EF FirstPostId是'FirstPost'的外键

让我知道这是否有效

更新

我已手动更改了您的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
您不能同时定义线程以要求postID和post以要求threadID,如果您这样做,您将无法创建任何一个线程,除非您同时创建这两个线程,这意味着在同一db.savechanges中


想想看。您希望使用尚未存在的帖子定义线程。

根本问题是,您的模型包含帖子和线程之间的1:1关联,其中线程是原则实体或独立实体。这是由…部分表示的

modelBuilder.Entity .HasOptionalt=>t.FirstPost .必须 您可以看到它反映在DDL语句中

ALTER TABLE`Posts`添加约束线程\u Post 外键Id 引用`Threads`Id 所以Post的主键也是线程的外键。这意味着您不能在每个线程中插入多个帖子!因为每个后续帖子都必须有一个新的PK值,但这并不引用现有的线程,所以会出现约束冲突

你可以通过让Post成为主要实体来解决这个问题。在这种情况下,线程将有一个PK/FK组合,引用它的第一个Post。然而,对我来说,1:1的联想传达出实体与几乎是一个学生的点密切相关。所以我认为1:1的组合在这里并不合适

我建议使用以下映射:

modelBuilder.Entity .HasOptionalt=>t.FirstPost .有很多 .HasForeignKeyt=>t.firstposted .willcascade.false; modelBuilder.Entity .HasRequiredp=>p.线程 .WithManyt=>t.回复 .HasForeignKeyp=>p.ThreadId .willcascade.false; 从理论上讲,这会将线程和FirstPost之间的关系转换为1对多,但实际上这意味着线程现在有一个外键指向它的第一篇文章,而这些复杂的PK/FK组合就消失了。请注意,FirstPostId应该是可为null的int,以支持此操作


另一方面,如果你认为一个线程和它的第一个帖子是紧密相关的,你可以考虑将两者合并到一个线程中,该线程还具有它的第一个后创建日期、内容的属性。你会得到一个非常简单的线程模型?对于仍然没有多余内容的回复。

它表示外键约束失败,与删除时的级联无关。当您向数据库添加条目时,您只需确保所有FK都与它们所引用的导航属性上的键相匹配,即使它们以后被更改,也必须将它们设置为相同的临时值我编辑了我在研究此错误时发现的一些页面。我认为这里的重点是更新而不是删除,因为我不删除数据,而是更新线程。创建线程后,FK正常,EF正确加载Id为1的FirstPost。这就是我无法理解此错误的原因-我认为我必须为更新指定一个操作,而不是不指定操作,但我不知道如何执行此操作。我认为它只提到了插入时失败的完整约束。在thread类中,尝试在公共虚拟Post FirstPost{get;set;}上方添加[ForeignKeyFirstPostId]您需要使用System.ComponentModel.DataAnnotations;因此,这给了我一个错误,即在Post模型中找不到FK。我以为应该是[ForeignKeyFirstPost]并且在FirstPostId attibute之上,但这不起作用@很抱歉,我无法真正理解你想说什么。我已将Thread.FirstPostId重命名为Thread.PostId=>无效,再次无法添加或更新子行。。。错误使用ForeignKey属性,我得到一个异常,该属性无效,因为在Post模型中找不到PostId。我认为该属性应该是ForeignKeyFirstPost,并放置在PostId之上-然后无效属性的异常消失,但是我再次得到无法添加或更新子行异常,因为FK FirstPost:如果您尝试重命名该字段
ds,也将FirstPost重命名为Post。还可以发布数据库表定义吗?我重命名了FirstPost属性,但仍然相同。您可以在这里看到EF生成的定义:您是指生成表的普通SQL?您在fluent API更改之前提供了代码。在VisualStudio中->打开服务器资源管理器->连接到数据库->在表上单击鼠标右键->单击“打开表定义->在那里可以看到代码。尝试加载它您的代码给了我一个错误,无法找到任务之间的正确映射-但我现在理解了问题的原因。我的第一种方法是使用继承,就像你说的线程从Post继承一样。邮件的问题是:我想在以后显示最新的内容,以便发布线程和帖子。当一个线程的第一个帖子是一个帖子时,这将更加容易和清晰,因此我可以简单地查询按CreationDate排序并按ThreadId分组的帖子表。但由于这不起作用,我将尝试向该线程添加一个LastPostTime属性,这样我就可以简单地查询按LastPostTime排序的线程表。这将导致一些冗余信息,但我认为没有更好的方法来实现这一点。您可能是说EF无法确定插入/更新的正确顺序?是的,这可能是一个问题,您可能应该先保存一个线程。合并的Thread/FirstPost类的优点是保存线程和post是一个原子操作,当然,这是一条记录。
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)
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;}
}
 public virtual Post FirstPost{get;set;}
[ForeignKey("FirstPostId")]
public virtual Post FirstPost{get;set;}
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