gpt4 book ai didi

entity-framework - 违反了 SQL Server 2008 的多重约束 - CodeFirst

转载 作者:行者123 更新时间:2023-12-04 05:26:42 25 4
gpt4 key购买 nike

我正在努力解决一个非常乏味的问题。
我有一个叫 Nation 的类(class)和一个叫 NationAlly 的类(class)

public class Nation   
{
public int ID {get; set;}
public int name {get;set;}
public List<NationAlly> NationAllies {get;set;}
}

public class NationAlly
{
public int ID {get; set;}
public int level {get;set;}
public Nation toNation {get;set;}
}

我使用 EF 4 和 CodeFirst 和一个名为 NationsDB 的 DbContext 来管理我在 SQL Server 2008 上的数据库。
如果我创建一个 Nation 类型的新对象并尝试调用nationsDB.SaveChanges,则会出现以下异常:

“违反了多重约束。关系'CodeFirstNamespace.NationAlly_toNation'的角色'NationAlly_toNation_Target'具有多重性1或0..1。”

我试图用 NationAllies 字段保存一个 Nation 并且没有抛出这个异常,数据库中的国家表获得了所有正确的值。

在我的数据库中,Nation 表有 2 个字段:ID(主键)、名称
NationAlly 表有 3 个字段:ID(主键)、级别、NationID
这两个表通过关系链接在一起,其中 NationAlly.NationID 是外键,Nation.ID 是主键。

不奇怪吗?在我看来,表 NationAlly 应该有一个名为 NationID1 的字段和另一个名为 NationID2 的字段,以创建一个国家和其他国家列表之间的“关系”。

我做错了什么?

最佳答案

您可能是 EF Code-First 映射约定的受害者,该约定会在 NationAllies 之间自动创建关系。和 toNation你不想拥有。

如果我理解正确(但我不是 100% 确定,如果我这样做),您实际上想要有两个关系,并且您只暴露了每个实体中关系的一端。所以,NationAllies不指向 toNation但是对于您NationAlly 中的“隐形”所有者国家实体。

如果是这种情况,您需要明确覆盖约定映射。在 EF 4.1 的 Fluent API 中,这可能如下所示:

public class MyContext : DbContext
{
public DbSet<Nation> Nations { get; set; }
public DbSet<NationAlly> NationAllies { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Nation>()
.HasMany(n => n.NationAllies)
.WithRequired()
.Map(conf => conf.MapKey("OwnerID"))
.WillCascadeOnDelete(false);

modelBuilder.Entity<NationAlly>()
.HasRequired(a => a.toNation)
.WithMany()
.Map(conf => conf.MapKey("NationID"))
.WillCascadeOnDelete(false);
}
}

此映射将创建两个外键 OwnerIDNationIDNationAllies表,都指向主键 IDNations table 。

编辑

这是我测试过的应用程序:
  • 在 VS2010/.NET 4.0 中新建一个 Console App,命名为“NationsApp”
  • 添加对“EntityFramework.dll”的引用
  • 清除“Program.cs”的内容并将以下内容粘贴到:

  • Program.cs的内容:
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;

    namespace NationsApp
    {
    public class Nation
    {
    public int ID { get; set; }
    public int name { get; set; }
    public List<NationAlly> NationAllies { get; set; }
    }

    public class NationAlly
    {
    public int ID { get; set; }
    public int level { get; set; }
    public Nation toNation { get; set; }
    }

    public class NationsContext : DbContext
    {
    public DbSet<Nation> Nations { get; set; }
    public DbSet<NationAlly> NationAllies { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    modelBuilder.Entity<Nation>()
    .HasMany(n => n.NationAllies)
    .WithRequired()
    .Map(conf => conf.MapKey("OwnerID"))
    .WillCascadeOnDelete(false);

    modelBuilder.Entity<NationAlly>()
    .HasRequired(a => a.toNation)
    .WithMany()
    .Map(conf => conf.MapKey("NationID"))
    .WillCascadeOnDelete(false);
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    using (var context = new NationsContext())
    {
    try
    {
    // We have three Nations and two Allies
    Nation nation1 = new Nation() {
    NationAllies = new List<NationAlly>() };
    Nation nation2 = new Nation() {
    NationAllies = new List<NationAlly>() };
    Nation nation3 = new Nation() {
    NationAllies = new List<NationAlly>() };
    NationAlly ally1 = new NationAlly();
    NationAlly ally2 = new NationAlly();

    // Nation1 has two Allies
    // (Nation1 is the "owner" of both Allies)
    nation1.NationAllies.Add(ally1);
    nation1.NationAllies.Add(ally2);

    // toNation of ally1 refers to Nation2
    ally1.toNation = nation2;
    // toNation of ally2 refers to Nation3
    ally2.toNation = nation3;

    context.Nations.Add(nation1);
    context.Nations.Add(nation2);
    context.Nations.Add(nation3);

    context.SaveChanges();
    }
    catch (Exception e)
    {
    throw;
    }
    }
    }
    }
    }

    您可以在“throw”上设置断点以观察调试器中 e 中可能出现的异常。

    这将创建一个名为 NationsApp.NationsContext 的数据库如果您使用的是 SQL Server Express 并且没有定义任何进一步的连接字符串。

    它给出了两个关系 Nation_NationAllies (FK 是“所有者 ID”)和 NationAlly_toNation (FK 是“NationID”)。所有列都是不可为空的。 DB中的结果如下:

    Nations and NationAllies

    关于entity-framework - 违反了 SQL Server 2008 的多重约束 - CodeFirst,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5422947/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com