Причина создания ошибки конфигурации codefirst?

Я новичок в первом поколении базы данных 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 (1-е отношение)
  • Имеет ноль или одно преобразование типа EntityChild (2-е отношение)

Цель состоит в том, чтобы иметь в EntityParent свойства:

  • Список детей.
  • EntityChildren, содержащий начальную позицию.

И в EntityChildren свойства:

  • Список EntityParent, у которых эта сущность является начальной позицией
  • EntityParent этого EntityChildren
  • EntityChildrenSource
  • EntityChildrenTarget

НО при выполнении команды для генерации скриптов базы данных у меня появляется следующая ошибка:

System.Reflection.TargetInvocationException: исключение было выброшено целью вызова. ---> System.InvalidOperationException: Невозможно определить отношение, представленное свойством навигации EntityChildren.TransformedParents типа ICollection. Либо настройте связь вручную, либо проигнорируйте это свойство с помощью атрибута «[NotMapped]» или с помощью EntityTypeBuilder.Ignore в «OnModelCreating». в Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.PropertyMappingValidationConvention.Apply (InternalModelBuilder modelBuilder) в Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelBuilt (InternalModelBuilder modelBuil дер) в Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel (контекст DbContext, соглашение IConventionSetBuilderSetBuilder, 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 дер) в Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel (контекст DbContext, соглашение IConventionSetBuilderSetBuilder, IModelValidator v алидатор)

Любая помощь, пожалуйста

1
0
143
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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);
    }

Я забыл указать, что между этими сущностями существуют следующие отношения: EntityParent: - Имеет один или несколько дочерних элементов типа EntityChild (1-е отношение) - Имеет ноль или одно преобразование типа EntityChild (2-е отношение). Это можно решить с помощью решения, приведенного выше?

kba 10.09.2018 11:25
Ответ принят как подходящий

В EF Core каждый отношение состоит из 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)
    ;

Другие вопросы по теме