【问题标题】:EF One to Zero or One relationship on existing tables leads to error on database updating现有表上的 EF 一对零或一对关系导致数据库更新错误
【发布时间】:2017-04-10 14:21:10
【问题描述】:

实体框架 6 - 代码优先。 我们的数据库中有一段时间的现有类及其表。这些表已经包含我们无法删除的数据。

我们尝试在它们之间添加“一到零或一”的关系,如下所示:

public class Session
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [ForeignKey("User")]
    public long Id { get; set; }
    ...
    public virtual User User { get; set;}
}

public class User
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [ForeignKey("Session")]
    public long Id { get; set; }
    ...
    public virtual Session Session { get; set;}
}

这是它根据上述更改创建的迁移:

public partial class AddingSessionAndDialogOneToOneRelation : DbMigration
{
    public override void Up()
    {
        CreateIndex("dbo.Users", "Id");
        AddForeignKey("dbo.Users", "Id", "dbo.Sessions", "Id");
    }

    public override void Down()
    {
        DropForeignKey("dbo.Users", "Id", "dbo.Sessions");
        DropIndex("dbo.Users", new[] { "Id" });
    }
}

但是当我们运行 Update-Database 命令时,我们得到这个错误:

ALTER TABLE 语句与 FOREIGN KEY 约束“FK_dbo.Users_dbo.Sessions_Id”冲突。冲突发生在数据库“SVC_AAA”、表“dbo.Sessions”、列“Id”中。

【问题讨论】:

  • 如果你有一对零或一对一的关系,它不适用于外键......
  • @AntoinePelletier 那我该怎么办?
  • 你不能在两端都有ForeignKey属性,我猜Session在你的情况下是可选的,所以从你的User PK中删除FK属性。
  • @FlorianHaider 我试过了。它会生成相同的迁移和相同的错误。
  • 完全不要使用外键,想象一下你的外键没有创建它,只是一个没有约束的字段,就是代表另一个表的id的int

标签: c# entity-framework ef-code-first


【解决方案1】:

我认为您使类定义过于复杂,并且两个 Id 上的 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 属性也可能导致问题。它可能应该只在用户 ID 上,但如果您遵循 Code-First 密钥约定,则根本不需要它。

以下代码无需额外的 DataAnnotations 就可以很好地工作:

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    [ForeignKey("Student")]
    public int StudentAddressId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

您可以在 http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx 找到许多创建代码优先关系的使用示例

更新:

对于更复杂的类,请尝试以下操作:

public class Session
{
    [Key]
    [ForeignKey("User")]
    public long Id { get; set; }
    ...
    public virtual User User { get; set;}
}

public class User
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }
    ...
    public virtual Session Session { get; set;}
}

【讨论】:

  • 这是经典的基本模型定义。当然可以,因为它非常简单。 EF 可以从简单模型中预测规则并相应地生成数据库。例如:它会自动将 Student.StudentId 定义为主键而不是 null 和身份,而无需您明确宣布。当事情变得更复杂并且模型类需要更多的关系并包含更多的数据(如在现实世界中)时,我们必须明确地告诉 EF 规则和关系。
  • 但是,正如我所写的,我试图以这种风格定义它,但在创建迁移时出错,我必须通过映射或数据注释明确定义这种关系。不过谢谢你。
  • 这样定义时遇到了什么错误?是同一个错误还是不同的错误?
  • 无法确定类型“Web_Model.User”和“Web_Model.Session”之间关联的主体端。此关联的主体端必须使用关系流式 API 或数据注释显式配置。
  • 我更新了帖子,说明您的课程应该如何注释。这应该会为您提供您正在寻找的 1 到 0 或 1 模型。
猜你喜欢
  • 2019-01-26
  • 2019-07-25
  • 2021-06-25
  • 1970-01-01
  • 2014-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多