c# - EF6 代码第一个多重一对多映射问题/"Multiplicity"错误

标签 c# entity-framework database-design ef-code-first entity-framework-6

我在尝试创建数据库时收到以下错误:

One or more validation errors were detected during model generation:

Interaction_CauseElement_Source: : Multiplicity is not valid in Role 'Interaction_CauseElement_Source' in relationship 'Interaction_CauseElement'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.

Interaction_EffectElement_Source: : Multiplicity is not valid in Role 'Interaction_EffectElement_Source' in relationship 'Interaction_EffectElement'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.

我在其他 Stack Overflow 帖子中看到过这个错误,但在我发现的示例中,OP 试图在表之间的两个方向上建立一对一的关系。这不是我要找的。

这是我的模型:

public class Element
{
    [Key]
    public int ID { get; set; }

    [Required, MaxLength(64)]
    public string Name { get; set; }

    [MaxLength(200)]
    public string Description { get; set; }
}

public class Interaction
{
    [Key]
    public int ID { get; set; }

    [Index, Required]
    public int CauseID { get; set; }

    [Index, Required]
    public int EffectID { get; set; }

    [MaxLength(64)]
    public string Location { get; set; }    

    [ForeignKey("CauseID")]
    public virtual Element CauseElement { get; set; }

    [ForeignKey("EffectID")]
    public virtual Element EffectElement { get; set; }
}

元素表中的项目是唯一的。一对元素可以在任意数量的位置相互作用。 CauseID/EffectID 对不会是唯一的。

我要更改模型的唯一其他地方是 OnModelCreating方法。我收到了这个错误:

Introducing FOREIGN KEY constraint 'FK_dbo.Interactions_dbo.Elements_Cause' on table 'Interactions' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint. See previous errors.

并且必须为模型创建级联策略。此代码修复了该错误:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    //Prevent cyclic cascade on elements table
    modelBuilder.Entity<Interaction>()
        .HasRequired(i => i.CauseElement)
        .WithRequiredDependent()
        .WillCascadeOnDelete(false);
    modelBuilder.Entity<Interaction>()
        .HasRequired(i => i.EffectElement)
        .WithRequiredDependent()
        .WillCascadeOnDelete(false);

    base.OnModelCreating(modelBuilder);
}

但随后我收到了神秘的“多重性”错误。好像它要我做 public virtual Element CauseElement进入像 public virtual ICollection<Element> CauseElement 这样的集合,但这并不能正确地模拟这种关系。

最佳答案

我找到了解决方案。 This article on EntityFrameworkTutoral.net helped out.因为我需要从 Interaction 类到 Element 类的两个引用,所以这种关系太复杂而无法在 EF 中仅使用属性进行建模。

我必须更新模型,然后使用流畅的 API 告诉 EF 如何处理关系。我将模型更新为以下内容:

public class Element
{
    public Element()
    {
        CauseElements = new List<Interaction>();
        EffectElements = new List<Interaction>();
    }

    [Key]
    public int ID { get; set; }

    [Required, MaxLength(64)]
    public string Name { get; set; }

    #region Navigation

    public virtual ICollection<Interaction> CauseElements { get; set; }
    public virtual ICollection<Interaction> EffectElements { get; set; }

    #endregion
}

public class Interaction
{
    [Key]
    public int ID { get; set; }

    [Index]
    public int CauseID { get; set; }

    [Index]
    public int EffectID { get; set; }

    [MaxLength(64)]
    public string Location { get; set; }

    #region Navigation

    [ForeignKey("CauseID")]
    public virtual Element CauseElement { get; set; }

    [ForeignKey("EffectID")]
    public virtual Element EffectElement { get; set; }

    #endregion
}

在我的 DbContext 类中,我使用流畅的 API 在 Interaction.CauseElementElement.CauseElements 之间创建链接,并且哪个属性是 Interaction表(与Effect关系同):

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    //Prevent cyclic cascade on elements table
    modelBuilder.Entity<Interaction>()
        .HasRequired(i => i.CauseElement)
        .WithRequiredDependent()
        .WillCascadeOnDelete(false);
    modelBuilder.Entity<Interaction>()
        .HasRequired(i => i.EffectElement)
        .WithRequiredDependent()
        .WillCascadeOnDelete(false);

    //Create the links between the element, the key, and the collection
    modelBuilder.Entity<Interaction>()
        .HasRequired<Element>(i => i.CauseElement)
        .WithMany(e => e.CauseElements)
        .HasForeignKey(i => i.CauseID);
    modelBuilder.Entity<Interaction>()
        .HasRequired<Element>(i => i.EffectElement)
        .WithMany(e => e.EffectElements)
        .HasForeignKey(i => i.EffectID);

    base.OnModelCreating(modelBuilder);
}

当您具有简单的一对多关系时, Entity Framework 似乎会尝试自动推断表之间的关系。如果我从 Interaction 类中删除了 EffectElement(从 Element 中删除了 EffectElements),EF 就能够创建关系容易地。但是当我重新添加它时,我又收到错误。

由于 Element 类型在 Interaction 类中出现了两次,它不知道如何创建关系。我必须在 OnModelCreating 方法中明确定义它。

关于c# - EF6 代码第一个多重一对多映射问题/"Multiplicity"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30112549/

相关文章:

c# - ASP.net c# 基础问题

调试 Entity Framework 查询

sql-server - Entity Framework 4 Code First 与树

mysql - 计划计划数据库结构

c# - 标记类的接口(interface)或属性?

c# - 异常调用堆栈被截断而没有任何重新抛出

c# - 如何列出特定文件夹中的文件夹和文件

entity-framework - 如何使用 AutoMapper 将 DTO 映射到 Entity Framework 代理类?

oracle - 日期维度的代理键?

mysql - 数据库设计(自定义属性取决于另一个属性)- MySQL 或其他