C# 在M和N都是相同实体的情况下,如何建立M:N(多对多)关系?
我在实体框架方面有困难。我正试图建立一个数据模型,实体通过一个连接表引用它的对立面 我已经创建了实体样式和连接表样式C# 在M和N都是相同实体的情况下,如何建立M:N(多对多)关系?,c#,entity-framework,C#,Entity Framework,我在实体框架方面有困难。我正试图建立一个数据模型,实体通过一个连接表引用它的对立面 我已经创建了实体样式和连接表样式 [Table("Styles")] public class Style : FullAuditedEntity { public virtual string Name { get; set; } public virtual string ShortName { get; set; } public List<StyleXStyle>
[Table("Styles")]
public class Style : FullAuditedEntity
{
public virtual string Name { get; set; }
public virtual string ShortName { get; set; }
public List<StyleXStyle> Opposites { get; set; } = new List<StyleXStyle>();
}
尝试添加数据库迁移时,出现以下错误:
无法确定由类型为“List”的导航属性“Style.opposities”表示的关系。手动配置关系,或者使用“[NotMapped]”属性或使用“OnModelCreating”中的“EntityTypeBuilder.ignore”忽略此属性。
由于您需要自引用样式
实体的集合,因此对于此多对多映射,您应该有两个集合属性。一个导航到你的对立面,另一个导航到“alikes”。在我的示例中,我包含了第二个名为Alikes
的列表属性
这样,您就可以包括一个自定义映射,告诉EF这些映射是如何相关的:
使用基于属性的配置:
public class Style : FullAuditedEntity
{
[InverseProperty("Style")]
public List<StyleXStyle> Alikes { get; set; } = new List<StyleXStyle>();
[InverseProperty("Opposite")]
public List<StyleXStyle> Opposites { get; set; } = new List<StyleXStyle>();
}
public class StyleXStyle : FullAuditedEntity
{
[ForeignKey("Opposite")]
public virtual int OppositeId { get; set; }
public Style Opposite { get; set; }
[ForeignKey("Style")]
public virtual int StyleId { get; set; }
public Style Style { get; set; }
}
公共类样式:FullAuditedEntity
{
[反向属性(“样式”)]
公共列表Alikes{get;set;}=new List();
[反向属性(“反向”)]
公共列表对立面{get;set;}=new List();
}
公共类StyleXStyle:FullAuditedEntity
{
[外键(“对方”)]
公共虚拟int-OppositeId{get;set;}
公共样式对立面{get;set;}
[外键(“样式”)]
公共虚拟int-StyleId{get;set;}
公共样式样式{get;set;}
}
使用Fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// configures one-to-many relationship
modelBuilder.Entity<StyleXStyle>()
.HasRequired<Style>(s => s.Style)
.WithMany(g => g.Alikes)
.HasForeignKey<int>(s => s.StyleId);
// configures one-to-many relationship
modelBuilder.Entity<StyleXStyle>()
.HasRequired<Style>(s => s.Opposite)
.WithMany(g => g.Opposites)
.HasForeignKey<int>(s => s.OppositeId);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
//配置一对多关系
modelBuilder.Entity()
.HasRequired(s=>s.Style)
.有许多(g=>g.相似物)
.HasForeignKey(s=>s.StyleId);
//配置一对多关系
modelBuilder.Entity()
.HasRequired(s=>s.reversit)
.有许多(g=>g.对立面)
.HasForeignKey(s=>s.OppositeId);
}
上面对连接实体/表执行映射,以便您可以将其用作多对多关系。如果您需要跟踪关系本身的任何信息(例如,CreatedDate、CreatedBy、RelationDate等),这是必要的。但是,如果您不需要关系实体的其他信息,EF提供了自己的方法来按照约定映射此信息
在后一种情况下,您可以将实体直接映射到彼此,并完全忽略关系表。下面是一个简单的例子:
[Table("Styles")]
public class Style : FullAuditedEntity
{
public virtual string Name { get; set; }
public virtual string ShortName { get; set; }
public ICollection<Style> Opposites { get; set; }
public ICollection<Style> Alikes { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Style>()
.HasMany<Style>(s => s.Alikes)
.WithMany(c => c.Opposites)
.Map(cs =>
{
cs.MapLeftKey("OppositeId");
cs.MapRightKey("StyleId");
cs.ToTable("StyleXStyle");
});
}
[表格(“样式”)]
公共类样式:FullAuditedEntity
{
公共虚拟字符串名称{get;set;}
公共虚拟字符串短名称{get;set;}
公共ICollection对立面{get;set;}
公共ICollection Alikes{get;set;}
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasMany(s=>s.Alikes)
.有许多(c=>c.对立面)
.Map(cs=>
{
cs.MapLeftKey(“反对党”);
cs.MapRightKey(“StyleId”);
cs.ToTable(“StyleXStyle”);
});
}
上面的代码是为您的示例而编写的,我没有完全测试它,但以前也以相同的方式实现了它
嗯
[Table("Styles")]
public class Style : FullAuditedEntity
{
public virtual string Name { get; set; }
public virtual string ShortName { get; set; }
public ICollection<Style> Opposites { get; set; }
public ICollection<Style> Alikes { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Style>()
.HasMany<Style>(s => s.Alikes)
.WithMany(c => c.Opposites)
.Map(cs =>
{
cs.MapLeftKey("OppositeId");
cs.MapRightKey("StyleId");
cs.ToTable("StyleXStyle");
});
}