【问题标题】:Entity Framework "A relationship multiplicity constraint violation occurred"实体框架“发生关系多重性约束违规”
【发布时间】:2017-03-25 00:55:37
【问题描述】:

我今天早上从 Entity Framework 收到了这个错误:

发生关系多重性约束违规:EntityReference 不能有多个相关对象,但查询返回多个相关对象。这是一个不可恢复的错误。

错误是指UserAddress之间非常简单的一对多关系

public class User
{
    public Guid Id { get; set; }
    public virtual IList<Address> Addresses { get; set; }
} 

public class Address
{
    public Guid Id { get; set; }
    public User User { get; set; }
} 

我正在使用 Fluent API 来配置实体之间的关系,但在这种情况下,这种关系似乎很简单,一开始我没有指定任何特定的规则,而是让 EF “推断”了这种关系:

public class AddressConfiguration : EntityTypeConfiguration<Address>
{
    public AddressConfiguration()
    {
        HasKey(a => a.Id);
        Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
    }
}

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        HasKey(u => u.Id);
        Property(u => u.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
    }
}

但收到错误后,我尝试在 AddressConfiguration 中指定以下规则:

public class AddressConfiguration : EntityTypeConfiguration<Address>
{
    public AddressConfiguration()
    {
        HasKey(a => a.Id);
        Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
        HasOptional(x => x.User).WithMany(); // I tried adding this
    }
}

之后,我尝试生成一个新的自动迁移,这是我得到的:

public partial class AddressFixMigration : DbMigration
{
    public override void Up()
    {
        DropForeignKey("dbo.Addresses", "User_Id", "dbo.Users");
        AddColumn("dbo.Addresses", "User_Id1", c => c.Guid());
        CreateIndex("dbo.Addresses", "User_Id1");
        AddForeignKey("dbo.Addresses", "User_Id1", "dbo.Users", "Id");
    }

    public override void Down()
    {
        DropForeignKey("dbo.Addresses", "User_Id1", "dbo.Users");
        DropIndex("dbo.Addresses", new[] { "User_Id1" });
        DropColumn("dbo.Addresses", "User_Id1");
        AddForeignKey("dbo.Addresses", "User_Id", "dbo.Users", "Id");
    }
}

我觉得这很奇怪。 Db 之前似乎还不错,地址表有一个外键“User_Id”,但是在配置文件中指定一对多关系之后,EF 想要创建一个 不同的外键。为什么??

我也尝试指定HasOptional(x =&gt; x.User).WithMany().Map(x =&gt; x.MapKey("User_Id"));,但在这种情况下,当我尝试创建自动迁移时,我收到以下错误:

User_Id:名称:类型中的每个属性名称都必须是唯一的。属性名称“User_Id”已定义。

我的数据库似乎明显有问题,但我看不出是什么以及为什么。

【问题讨论】:

    标签: c# entity-framework entity-framework-migrations


    【解决方案1】:

    还有其他技术,但我更喜欢明确地放入 FK:

    public class Address
    {
        public Guid Id { get; set; }
        public Int? User_Id { get; set; }
        public User User { get; set; }
    } 
    

    然后使用这个流畅的代码:

    HasOptional(x => x.User).WithMany(x => x.Addresses).HasForeignKey(x => x.User_Id);
    

    【讨论】:

    • 我不能改变域的架构,我们做出这个选择是有原因的。另外,为什么您建议的更改会起作用?我的代码有什么问题?
    • 你不需要。如果 User_Id 是 FK,只需将其添加到您的模型并告诉流利的代码。 EF 尝试添加 User_Id1,因为它无法确定关系。
    • 好的,我刚刚尝试了你说的,当我尝试创建迁移时的结果是相同的:AddForeignKey("dbo.Addresses", "User_Id1", "dbo.Users", "Id")。这很奇怪,就像列已损坏或类似 thiat。
    • 天哪,我刚刚将.WithMany() 更改为.WithMany(x =&gt; x.Addresses),它开始工作了!没有创建迁移,错误消失了。我不明白:x =&gt; x.Addresses 不应该是隐含的吗?
    • 有很多 EF 的东西可以是隐式的,比如 UserId 自动被称为 FK,但我个人认为它让其他程序员更清楚地做到这一点。一般来说,除非出现问题,否则你不会看那些东西。
    【解决方案2】:

    我意识到我需要更改我的配置文件,如下所示:

    public class AddressConfiguration : EntityTypeConfiguration<Address>
    {
        public AddressConfiguration()
        {
            HasKey(a => a.Id);
            Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
            HasOptional(x => x.User).WithMany(x => x.Addresses).Map(x => x.MapKey("User_Id"));
        }
    }
    

    .WithMany()(不带参数)用于关系的另一端没有导航属性的情况,而在这种情况下,我需要分隔.WithMany(x =&gt; x.Addresses),因为User 实际上包含地址列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-30
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 2016-08-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多