Entity Framework — Связь между типами сущностей была разорвана проблема

#c# #asp.net-mvc #asp.net-core #entity-framework-core

#c# #asp.net-mvc #asp.net-core #entity-framework-core

Вопрос:

Привет, у меня возникла проблема с Entity Framework, когда я пытаюсь удалить строку в таблице «привязки».

Таблицы выглядят следующим образом:

 [Table("Users")]
public class UserEntity : BaseEntity
{
    [Required]
    [MaxLength(30)]
    public string Username { get; set; }
    [Required]
    [MaxLength(200)]
    public string Password { get; set; }

    [Required]
    [MaxLength(200)]
    public string Name { get; set; }

    [Required]
    [MaxLength(20)]
    public string Cellphone { get; set; }

    public virtual ICollection<UserGroupEntity> UserGroups { get; set; }


[Table("Groups")]
public class GroupEntity : BaseEntity
{
    [Required]
    [MaxLength(20)]
    public string Code { get; set; }

    [Required]
    [MaxLength(200)]
    public string Name { get; set; }
}
  

И теперь у меня есть таблица, которая связывает эти два вместе:

 [Table("UserGroups")]
public class UserGroupEntity : BaseEntity
{
    [Required]
    [ForeignKey("User")]
    public int UserId { get; set; }

    [Required]
    [ForeignKey("Group")]
    public int GroupId { get; set; }

    public virtual UserEntity User { get; set; }
    public virtual GroupEntity Group { get; set; }


}
  

Но когда я извлекаю идентификатор пользователя из базы данных и, например, беру первую группу пользователей и пытаюсь удалить ее, как показано ниже, я получаю сообщение об ошибке

             UserEntity user = _dataContext.Users
            .Include(x => x.UserGroups)
            .ThenInclude(x => x.Group)
            .SingleOrDefault(x => x.Id == model.Id amp;amp; !x.IsDeleted);


            UserGroupEntity userGroupBinding = user.UserGroups.First();
            user.UserGroups.Remove(userGroupBinding);

            _dataContext.SaveChanges();
  

Сообщение об ошибке, которое я получаю:

 The association between entity types 'UserEntity' and 'UserGroupEntity' has been severed but the relationship is either marked as 'Required' or is implicitly required because the foreign key is not nullable. If the dependent/child entity should be deleted when a required relationship is severed, then setup the relationship to use cascade deletes.  Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the key values.'
  

Мой метод создания DbContext ONMODEL выглядит следующим образом:

         protected override void OnModelCreating(ModelBuilder modelBuilder)
    {            
        var cascadeFKs = modelBuilder.Model.GetEntityTypes()
            .SelectMany(t => t.GetForeignKeys())
            .Where(fk => !fk.IsOwnership amp;amp; fk.DeleteBehavior == DeleteBehavior.Cascade);

        foreach (var fk in cascadeFKs)
            fk.DeleteBehavior = DeleteBehavior.Restrict;



        base.OnModelCreating(modelBuilder);
    }
  

У кого-нибудь есть идея, как решить эту проблему? Я много искал, но так и не нашел решения для моего случая.

Комментарии:

1. Удалить поведение. Restrict => Я думаю, это не позволит вам удалить

2. Существует открытая проблема, чтобы упростить это. github.com/dotnet/efcore/issues/10066

Ответ №1:

Это своего рода удивительное и нелогичное поведение как побочный эффект каскадного удаления (хотя удаление связанного объекта не имеет ничего общего с каскадным удалением, которое по определению должно контролировать то, что происходит при удалении основного объекта). Это даже задокументировано в разделе «Удаление связей» документации EF Core:

Вы можете удалить связь, установив для ссылочной навигации значение null или удалив связанную сущность из навигации по коллекции.

Удаление связи может иметь побочные эффекты для зависимой сущности в соответствии с поведением каскадного удаления, настроенным в связи.

и т.д.

В общем случае удаление зависимого объекта из свойства навигации по коллекции принципала следует рассматривать как разъединение (необязательная связь) или удаление (обязательная связь), но, по-видимому, текущая реализация EF Core также создает исключение для требуемой связи с отключением каскадного удаления (и некоторыми другими сценариями).

Единственный способ исправить это без активации каскадного удаления (которое вы OnModelCreating отключаете) — это удалить (remove) связанный объект непосредственно из соответствующего свойства навигации по коллекции DbSet или DbContext , а не из коллекции. например, заменить

 user.UserGroups.Remove(userGroupBinding);
  

с любым

 _dataContext.UserGroups.Remove(userGroupBinding);
  

или

 _dataContext.Set<UserGroup>().Remove(userGroupBinding);
  

или просто

 _dataContext.Remove(userGroupBinding);
  

В обоих случаях после вызова SaveChanges зависимый объект будет удален из базы данных и удален из свойства навигации коллекции исправлением свойства навигации EF Core.

Комментарии:

1. В моем случае метод удаления не работает, использовал этот обходной путь: foreach (var entity в entities) { контекст. Запись (сущность). Состояние = EntityState. Удалено; }