CodeFirst配置错误创建原因?

时间:2018-09-10 08:56:07

标签: c# asp.net-mvc entity-framework-core

我是EntityFramework Core Code首次数据库生成的初学者,并且我对两个实体的关系配置有疑问:

 public class EntityParent
    {
        public int Id { get; set; }
        public string Name { get; set; }

        //Navigation properties to the EntityChildren which have info of start position.
        [ForeignKey("TransformationEntity")]
        public int? TransformationEntityId { get; set; }
        public virtual EntityChildren TransformationEntity { get; set; }

        //Navigation property : List of childrens
        public virtual ICollection<EntityChildren> Childrens { get; set; }
    }

    public class EntityChildren
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int StartPosition { get; set; }

        //List of EntityParents which have this EntityChildren as the start position
        public virtual ICollection<EntityParent> TransformedParents { get; set; }

        //Relation one-to-one(this same table)
        [ForeignKey("EntityChildrenSource")]
        public int? Cadrage { get; set; }
        public virtual EntityChildren EntityChildrenSource { get; set; }
        public virtual EntityChildren EntityChildrenTarget { get; set; }

        //Navigation property to EntityParent
        [ForeignKey("Parent")]
        public int Parent_FK { get; set; }
        public virtual EntityParent Parent { get; set; }
    }

这些实体之间的关系是: EntityParent:

  • 具有一个或多个EntityChild类型的孩子(第一个关系)
  • 具有EntityChild类型(第二关系)的零或一转换

目标是在EntityParent中具有以下属性:

  • 孩子们的名单。
  • 包含开始位置的EntityChildren。

在EntityChildren中,属性:

  • 以该实体为起始位置的EntityParent列表
  • 此EntityChildren的EntityParent
  • EntityChildrenSource
  • EntityChildrenTarget

但是在执行命令以生成数据库脚本时却出现了以下错误:

System.Reflection.TargetInvocationException:调用的目标引发了异常。 ---> System.InvalidOperationException:无法确定类型为“ ICollection”的导航属性“ EntityChildren.TransformedParents”表示的关系。手动配置关系,或者使用“ [NotMapped]”属性或通过“ OnModelCreating”中的“ EntityTypeBuilder.Ignore”忽略此属性。    在Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.PropertyMappingValidationConvention.Apply(InternalModelBuilder modelBuilder)    在Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelBuilt(InternalModelBuilder modelBuil der)    在Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext上下文,IConventionSetBuilder ConventionSetBuilder,IModelValidator v 滑道)

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: **Unable to determine the relationship represented by navigation property 'EntityChildren.TransformedParents' of type 'ICollection<EntityParent>'**. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.PropertyMappingValidationConvention.Apply(InternalModelBuilder modelBuilder)上的

   在Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelBuilt(InternalModelBuilder modelBuil der)    在Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext上下文,IConventionSetBuilder ConventionSetBuilder,IModelValidator v 滑道)

请帮助

2 个答案:

答案 0 :(得分:1)

public class EntityChildren
{
     public virtual ICollection<EntityParent> TransformedParents { get; set; }    

public class EntityParent
{
     public virtual ICollection<EntityChildren> Childrens { get; set; }

创建EF Core不支持的多对多关系。

中产阶级必须解决这个问题

例如,类中间类ParentChildren

 public class ParentChildren
 {
        public int ParentId { get; set; }
        public EntityParent Parent{ get; set; }

        public int ChildId { get; set; }
        public EntityChild Child{ get; set; }
 }

然后,在ICollection<ParentChildren>EntityParent中使用EntityChild

DBContext

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<EntityParent>()
            .HasKey(x => x.Id);

        modelBuilder.Entity<EntityChild>()
            .HasKey(x => x.Id);

        modelBuilder.Entity<ParentChildren>()
            .HasKey(x => new { x.ParentId , x.ChildId });

        modelBuilder.Entity<ParentChildren>()
            .HasOne(x => x.Parent)
            .WithMany(m => m.Childrens)
            .HasForeignKey(x => x.ParentId);

        modelBuilder.Entity<ParentChildren>()
            .HasOne(x => x.Child)
            .WithMany(e => e.TransformedParents)
            .HasForeignKey(x => x.ChildId);
    }

答案 1 :(得分:1)

在EF Core中,每个relationship由0、1或2个导航属性组成。在大多数情况下,EF Core可以自动确定关系及其关联的导航属性。但是有时却不能,因此它会引发异常,并期望您通过数据注释,流畅的API或两者的结合来明确指定。

在这种特殊情况下,异常消息告诉您EF Core无法确定由EntityChildren.TransformedParents集合导航属性表示的关系。您可以使用[InverseProperty]数据注释将其与ParentEntity.TransformationEntity参考导航属性配对来解决它:

[InverseProperty(nameof(EntityParent.TransformationEntity))]
public virtual ICollection<EntityParent> TransformedParents { get; set; }

在这种情况下就足够了。

Fluent API更灵活,因为它们可以完全配置关系的所有方面-主体,从属,导航属性,从属FK属性,主体PK属性,必需/可选,级联删除行为等。相应的流利配置为像这样:

modelBuilder.Entity<EntityParent>()
    .HasOne(p => p.TransformationEntity)
    .WithMany(c => c.TransformedParents)
    .HasForeignKey(p => p.TransformationEntityId) // optional (by convention)
    .IsRequired(false) // optional (by convention)
    .OnDelete(DeleteBehavior.ClientSetNull) // optional (by convention)
    ;