EF6代码首先是多个1对多映射问题/" Multiplicity"错误

时间:2015-05-07 22:11:58

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

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

  

在模型生成期间检测到一个或多个验证错误:

     

Interaction_CauseElement_Source :: Multiplicity在Role中无效   ' Interaction_CauseElement_Source'谈恋爱   ' Interaction_CauseElement&#39 ;.因为依赖角色属性是   不是关键属性,多重性的上限   依赖角色必须是' *'。

     

Interaction_EffectElement_Source ::多重性在角色中无效   ' Interaction_EffectElement_Source'谈恋爱   ' Interaction_EffectElement&#39 ;.因为依赖角色属性是   不是关键属性,多重性的上限   依赖角色必须是' *'。

我在其他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; }
}

Elements表中的项目是唯一的。一对元素可以在任何数量的位置彼此交互。 CauseID / EffectID对不会是唯一的。

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

  

引入FOREIGN KEY约束   ' FK_dbo.Interactions_dbo.Elements_Cause'桌子上   '相互作用'可能会导致循环或多个级联路径。   指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他   FOREIGN KEY约束。无法创建约束。见前   错误。

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

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);
}

然后我收到了神秘的&#34; Multiplicity&#34;错误。似乎它希望我将public virtual Element CauseElement变成像public virtual ICollection<Element> CauseElement这样的集合,但这不能正确地模拟这种关系。

2 个答案:

答案 0 :(得分:1)

我找到了解决方案。 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表的外键(和效果关系):

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);
}

当您拥有简单的1对多关系时,似乎Entity Framework会尝试自动推断表之间的关系。如果我从EffectElement类(以及Interaction EffectElements)中删除Element,则EF可以轻松创建关系。但是当我把它添加回去时,我又收到了错误。

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

答案 1 :(得分:0)

您颠倒了“ForeignKey”属性的职责。它在ID字段上,指定它作为外键的属性。你想要的东西如下:

// To-One on Element 
[ForeignKey("Element")]
public int ElementId { get; set; }
public virtual Element Element { get; set; }

此外,这实际上是一对一的关系。在这种情况下,一对多的关系是:

// To-Many on Element 
public virtual ICollection<Element> Elements{ get; set; }