Entity framework 实体框架建模一对多关系
我不知道如何在EF中配置以下关系:Entity framework 实体框架建模一对多关系,entity-framework,one-to-many,Entity Framework,One To Many,我不知道如何在EF中配置以下关系: 假设我需要创建一些语言词典模型。我有一种语言和另一种语言的项目(例如单词)。这两项之间有某种联系 例如:“hund”(德语)->“dog”(英语),关系类型为“Translate” 公共枚举语言 { 英语, 德语, } 公共类项目 { 公共长ID{get;set;} [必需] 公共字符串值{get;set;} [必需] 公共语言{get;set;} 公共虚拟ICollection项关系{get;set;} } 公共枚举ItemRelationType { 翻译
假设我需要创建一些语言词典模型。我有一种语言和另一种语言的项目(例如单词)。这两项之间有某种联系 例如:“hund”(德语)->“dog”(英语),关系类型为“Translate”
公共枚举语言
{
英语,
德语,
}
公共类项目
{
公共长ID{get;set;}
[必需]
公共字符串值{get;set;}
[必需]
公共语言{get;set;}
公共虚拟ICollection项关系{get;set;}
}
公共枚举ItemRelationType
{
翻译,
同义词,
}
公共类项目关系
{
公共长ID{get;set;}
[外键(“项目ID”)]
公共项项{get;set;}
[外键(“相对项”)]
公共项RelativeItem{get;set;}
[必需]
public ItemRelationType类型{get;set;}
}
EF标准迁移在一种情况下抛出一些错误,或者在另一种情况下创建我不喜欢的列或FK(Item_ID
等)
我想我需要配置一些流畅的api-但我不确定如何…我想您可能可以解决这个问题:
public class ItemRelation
{
public long Id { get; set; }
[ForeignKey("PrimaryItemId")]
public Item Item { get; set; }
public long PrimaryItemId { get; set; }
[ForeignKey("RelatedItemId")]
public Item RelatedItem { get; set; }
public long RelatedItemId { get; set; }
public ItemRelationType RelationType;
}
请注意,该类现在与项
实体有两个关系,从而产生两个外键。请注意,每个项
属性都有一个[ForeignKey]
属性,字符串参数指定要用作外键列的长
将此答案视为在不同轨道上的轻推。进一步研究这个主题,看看它是否适合您的用例 我想你也许能逃脱这个惩罚:
public class ItemRelation
{
public long Id { get; set; }
[ForeignKey("PrimaryItemId")]
public Item Item { get; set; }
public long PrimaryItemId { get; set; }
[ForeignKey("RelatedItemId")]
public Item RelatedItem { get; set; }
public long RelatedItemId { get; set; }
public ItemRelationType RelationType;
}
请注意,该类现在与项
实体有两个关系,从而产生两个外键。请注意,每个项
属性都有一个[ForeignKey]
属性,字符串参数指定要用作外键列的长
将此答案视为在不同轨道上的轻推。进一步研究这个主题,看看它是否适合您的用例 您缺少实际的FK字段
ItemID
和RelativeItemID
:
要配置导航属性,可以使用InverseProperty
属性,同时禁用一点EF约定(如下所示)
上面的声明使用了virtual
,以便延迟加载工作。这不是必需的,您可以将其删除。结果是延迟加载无法工作,这也没关系
假设您需要第二个关系的导航属性,则需要添加该属性:
public class Item
{
...
public virtual ICollection<ItemRelation> RelativeItemRelations { get; set; }
...
}
此解决方案应该可以工作,但它有效地禁用了对所有一对多关系的级联删除。好处是,您可以通过使用fluentapi在个案的基础上重新获得它
实现目标的第二种方法是使用fluent api,如下所示:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
...
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
...
将第二个导航属性添加到项目实体:
public class Item
{
...
public virtual ICollection<ItemRelation> RelativeItemRelations { get; set; }
...
}
要配置导航属性并避免级联问题,只需使用fluent api定义关系:
public TheContext : DbContext
{
public DbSet<Item> Items { get; set; }
public DbSet<ItemRelation> ItemRelations { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ItemRelation>()
.HasRequired(e => e.Item)
.WithMany(t => t.ItemRelations)
.HasForeignKey(e => e.ItemID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<ItemRelation>()
.HasRequired(e => e.RelatedItem)
.WithMany(t => t.RelativeItemRelations)
.HasForeignKey(e => e.RelativeItemID)
.WillCascadeOnDelete(false);
// Uncomment the following if you want to disable all cascading deletes and automatic fk creation conventions
// modelBuilder.Conventions.Remove<ForeignKeyIndexConvention>();
// modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
// modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
...
}
}
public上下文:DbContext
{
公共数据库集项{get;set;}
公共数据库集项关系{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
基于模型创建(modelBuilder);
modelBuilder.Entity()
.has必需(e=>e.Item)
.WithMany(t=>t.ItemRelations)
.HasForeignKey(e=>e.ItemID)
.WillCascadeOnDelete(假);
modelBuilder.Entity()
.HasRequired(e=>e.RelatedItem)
.与许多(t=>t.RelativeItemRelations)
.HasForeignKey(e=>e.RelativeItemID)
.WillCascadeOnDelete(假);
//如果要禁用所有级联删除和自动fk创建约定,请取消注释以下内容
//modelBuilder.Conventions.Remove();
//modelBuilder.Conventions.Remove();
//modelBuilder.Conventions.Remove();
...
}
}
您缺少实际的FK字段ItemID
和RelativeItemID
:
要配置导航属性,可以使用InverseProperty
属性,同时禁用一点EF约定(如下所示)
上面的声明使用了virtual
,以便延迟加载工作。这不是必需的,您可以将其删除。结果是延迟加载无法工作,这也没关系
假设您需要第二个关系的导航属性,则需要添加该属性:
public class Item
{
...
public virtual ICollection<ItemRelation> RelativeItemRelations { get; set; }
...
}
此解决方案应该可以工作,但它有效地禁用了对所有一对多关系的级联删除。好处是,您可以通过使用fluentapi在个案的基础上重新获得它
实现目标的第二种方法是使用fluent api,如下所示:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
...
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
...
将第二个导航属性添加到项目实体:
public class Item
{
...
public virtual ICollection<ItemRelation> RelativeItemRelations { get; set; }
...
}
要配置导航属性并避免级联问题,只需使用fluent api定义关系:
public TheContext : DbContext
{
public DbSet<Item> Items { get; set; }
public DbSet<ItemRelation> ItemRelations { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ItemRelation>()
.HasRequired(e => e.Item)
.WithMany(t => t.ItemRelations)
.HasForeignKey(e => e.ItemID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<ItemRelation>()
.HasRequired(e => e.RelatedItem)
.WithMany(t => t.RelativeItemRelations)
.HasForeignKey(e => e.RelativeItemID)
.WillCascadeOnDelete(false);
// Uncomment the following if you want to disable all cascading deletes and automatic fk creation conventions
// modelBuilder.Conventions.Remove<ForeignKeyIndexConvention>();
// modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
// modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
...
}
}
public上下文:DbContext
{
公共数据库集项{get;set;}
公共数据库集项关系{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
基于模型创建(modelBuilder);
modelBuilder.Entity()
.has必需(e=>e.Item)
.WithMany(t=>t.ItemRelations)
.HasForeignKey(e=>e.ItemID)
.WillCascadeOnDelete(假);
modelBuilder.Entity()
.HasRequired(e=>e.RelatedItem)
.与许多(t=>t.RelativeItemRelations)
.HasForeignKey(e=>e.RelativeItemID)
.WillCascadeOnDelete(假);
//如果要禁用所有级联删除和自动fk创建约定,请取消注释以下内容