Я работаю с Entity Framework Core 3.0 и у меня возникают проблемы с вставкой объектов в свойства навигации и должным образом поддерживающим Родительский внешний ключ.
У меня есть 2 класса моделей
EntityType.cs
public class EntityType
{
public int TypeId { get; set; }
public string Name { get; set; }
public virtual ICollection<Criteria> Criterias { get; set; }
}
Criteria.cs
public class Criteria
{
public int CriteriaId { get; set; }
public int TypeId { get; set; }
public int? ParentCriteriaId { get; set; }
public string Name { get; set; }
public virtual EntityType Type { get; set; }
public virtual Criteria ParentCriteria { get; set; }
public virtual ICollection<Criteria> Criterias { get; set; }
}
Таким образом, как вы можете видеть, «Тип» может иметь один или несколько «Критериев» икаждый «критерий» может иметь один или несколько дочерних «критериев». Таким образом, «Критерии» имеют FK с самоссылкой.
Вот отношение конфигурации FluentApi, которое у меня есть для «Критерии»
builder.HasOne(x => x.Type).WithMany(x => x.Criterias).HasForeignKey(x => x.TypeId).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(x => x.ParentCriteria).WithMany(x => x.Criterias).HasForeignKey(x => x.ParentCriteriaId).OnDelete(DeleteBehavior.Restrict);
Итак, я реализовал шаблон UnitOfWork / Repository и получил сервисслой, который использует это. Мой сервисный слой для вставки «EntityType» вместе с одним или многими «критериями» выглядит следующим образом -
- Обратите внимание, что это сервисный слой, и вызывающая сторона передает объект «EntityTypeDTO», которыйсодержит список объектов «Критерии», и у меня также есть логика для создания списка «детей», который здесь не показан.
// The main parent object to be created
EntityType type = new EntityType
{
Name = entityTypeDTO.Name
};
foreach (CriteriaDTO criteriaDTO in entityTypeDTO.Criterias)
{
// Create the top level Criteria object which will be the "Parent"
// No problem here, EF is able to populate the TypeId FK for the Parent
Criteria criteria= new Criteria
{
Name = criteriaDTO.Name
};
foreach (CriteriaDTO childDTO in children)
{
// Loop through the children of the parent and add to the navigation property
// Here is where the problem is, EF is able to populate the ParentCriteriaId FK but
// for some reason cannot resolve the TypeId FK
criteria.Criterias.Add(new ModelCriteria
{
Name = childDTO.Name
});
}
type.Criterias.Add(criteria);
}
UnitOfWork.ModelTypeRepository.Add(type);
await UnitOfWork.SaveAsync();
Поэтому после попытки сохранения я получаю следующее исключение: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Criteria_EntityTypes_TypeId". The conflict occurred in database
Итак, я знаю, где возникает проблема, но не знаю, почему. EF не может разрешить TypeId при циклическом просмотре дочерних элементов Criteria и добавлении в коллекцию критериев.Criterias. В настоящее время я использую следующий обходной путь -
Вместо добавления дочернего объекта критериев в список «Критерии», например, так:
foreach (CriteriaDTO childDTO in children)
{
criteria.Criterias.Add(new ModelCriteria
{
Name = childDTO.Name
});
}
Я должен вручную установить EntityTypeобъект вроде этого (но я не должен был делать это так):
foreach (CriteriaDTO childDTO in children)
{
criteria.Criterias.Add(new ModelCriteria
{
Name = childDTO.Name,
EntityType = type
});
}