Подтвердить что ты не робот

Отношение находится в состоянии "Удалено"

Когда я пытаюсь очистить коллекцию (вызов .Clear), я получаю следующее исключение:

Произошла ошибка при сохранении объектов, которые не отображают свойства внешнего ключа для своих отношений. Свойство EntityEntries вернет значение null, потому что один объект не может быть идентифицирован как источник исключения. Обработка исключений при сохранении может быть упрощена путем отображения свойств внешнего ключа в ваших типах объектов. Подробнее см. В InnerException.

Внутреннее исключение:

Отношения "Association_Availability" AssociationSet находятся в состоянии "Удалено". Учитывая ограничения множественности, соответствующий "User_Availability_Target" также должен находиться в состоянии "Удалено".

Пользователь выглядит так:

....
ICollection<Availability> Availability { get; set; }

Доступность выглядит следующим образом:

int ID { get; set; }
User User { get; set; }
DateTime Start { get; set;
DateTime End { get; set; }

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

HasMany(x => x.Availability).WithRequired(x => x.User);
HasRequired(x => x.User).WithMany(x => x.Availability);

Код, вызывающий проблему:

user.Availability.Clear();

Я рассмотрел другие варианты, такие как использование DbSet для удаления элементов, но я не чувствую, что мой код будет таким же чистым. Есть ли способ сделать это, очистив коллекцию?

4b9b3361

Ответ 1

Единственный способ заставить его работать, как я знаю, - это определить отношения как идентифицирующие отношения. Требуется ввести внешний ключ от Availability для User в качестве внешнего ключа в вашу модель...

public int ID { get; set; }
public int UserID { get; set; }
public User User { get; set; }

... и сделать его частью первичного ключа:

modelBuilder.Entity<Availability>()
    .HasKey(a => new { a.ID, a.UserID });

Вы можете расширить свое отображение, включив в него этот внешний ключ (просто чтобы быть явным, это не требуется, потому что EF распознает его по соглашению):

modelBuilder.Entity<Availability>()
    .HasRequired(a => a.User)
    .WithMany(u => u.Availability)
    .HasForeignKey(a => a.UserID);

(Кстати: вам нужно настроить отношения только с одной стороны. Не обязательно иметь оба этих сопоставления в вашем вопросе.)

Теперь вы можете очистить коллекцию с помощью user.Availability.Clear(); и объекты Availability будут удалены из базы данных.

Ответ 2

Есть один трюк. Вы можете удалить объекты без использования специального DbSet:

(this.dataContext as IObjectContextAdapter).ObjectContext.DeleteObject(entity);

Выполните это для каждого элемента в коллекции доступности перед его очисткой. Вам не нужно "идентифицировать отношения" для этого пути.

Ответ 3

В случае, если у кого-то есть такая же проблема с использованием SQLite:

К сожалению, принятый ответ не работает с SQLite, потому что SQLite не поддерживает автоинкремент для составных ключей.

Вы также можете переопределить метод SaveChanges() в контексте базы данных, чтобы удалить дочерние элементы:

//// Long Version
//var localChilds = this.SubCategories.Local.ToList();
//var deletedChilds = localChilds.Where(w => w.Category == null).ToList();
//foreach(var child in deletedChilds) {
//   this.SubCategories.Remove(child);
//}

// Short in LINQ
this.SubCategories.Local
    .Where(w => w.Category == null).ToList()
    .ForEach(fe => this.SubCategories.Remove(fe));
#endregion

Смотрите этот великий пост в блоге как мой источник (к сожалению, на немецком языке).