Entity framework 实体框架建模一对多关系

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 { 翻译

我不知道如何在EF中配置以下关系:


假设我需要创建一些语言词典模型。我有一种语言和另一种语言的项目(例如单词)。这两项之间有某种联系

例如:“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创建约定,请取消注释以下内容