尝试创建数据库时收到以下错误:
在模型生成期间检测到一个或多个验证错误:
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
这样的集合,但这不能正确地模拟这种关系。
答案 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.CauseElement
和Element.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; }