Удаление объектов в правильном порядке с помощью EF

#.net #sql #asp.net-mvc #entity-framework

#.net #sql #asp.net-mvc #entity-framework

Вопрос:

У меня есть два класса, созданные Entity Framework на основе таблиц в моей БД

 public class AttributeDefinition
{
    int id { get; set; }
    string Type { get; set; }
    string Description { get; set; }
    EntityCollection<AttributeValue> AttributeValues { get; set; }
}

public class AttributeValue
{
    int id { get; set; }
    string Value { get; set; }
    AttributeDefinition AttributeDefinition { get; set; }
}
  

В базе данных связь определяется столбцом внешнего ключа AttributeDefinitionID в AttributeValue таблице.

Случай, когда я хочу удалить, заключается в следующем:

 if (definition.AttributeValues.Count == 1)
    _db.AttributeValues.DeleteObject(definition.AttributeValues.First());
/*
else if (definition.AttributeValues.Count == 0)
    nothing needs to be done
else if (definition.AttributeValues.Count > 1)
    allow delete of AttributeDefinition, constraint will throw error on save
    which is caught and handled to output error
*/

_db.AttributeDefinitions.DeleteObject(definition);
_db.SaveChanges();
  

Я думал, что это должно сработать, однако, похоже, сначала пытается удалить AttributeDefinition, поэтому я получаю ошибку ограничения ссылки:

Оператор УДАЛЕНИЯ конфликтовал со ссылочным ограничением «FKAttributeV644147». Конфликт произошел в базе данных «Test», таблица «dbo.Значение атрибута», столбец ‘AttributeDefinitionID’. Оператор был завершен.

Если я сохраняю между удалениями, все работает нормально:

 if (definition.AttributeValues.Count == 1)
{
    _db.AttributeValues.DeleteObject(definition.AttributeValues.First());
    _db.SaveChanges();  //Save between deletes
}

_db.AttributeDefinitions.DeleteObject(definition);
_db.SaveChanges();
  

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

Есть идеи?

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

1. Ручной SQL удалит все значения, которые указывают на определение 1, а не только первое. Вы уверены, что в базе данных был только один?

2. Да, я это понимаю, и да, есть только один. В другом примере, если я удаляю значение атрибута в своем контроллере, затем сохраняю, затем удаляю определение атрибута в своем контроллере, затем снова сохраняю, это также работает нормально.

3. Есть ли у вас ссылочное ограничение в базе данных?

4. Да, это то, что выдает ошибку. Если значение атрибута удаляется до определения атрибута, все в порядке, как в моих примерах. Однако, похоже, что EF пытается удалить определение атрибута перед удалением значения атрибута.

Ответ №1:

Так что это может быть особый случай, но я решил добавить ответ на всякий случай, если люди были заинтересованы или искали его.

Как оказалось, EF не импортировала ссылочное ограничение из базы данных при обновлении модели. Я решил это, просмотрев Ограничения в браузере моделей. Это привело к тому, что он не знал порядок удаления объектов при сохранении в базе данных.

Как только я разобрался с этим, я знал по предыдущему опыту, что если вы добавляете некластеризованный индекс к первичному ключу, который используется в ограничении, EF с трудом подгоняет и не импортирует его. Подробности смотрите здесь.

Итак, я просто удалил индекс, повторно перенес ограничение, и теперь все работает так, как должно.