Удалить Каскад не работает с NHibernate
У меня есть таблица Communication, в которой есть ссылка на PersonCompany. В сопоставлении для PersonCompany я определил Cascade-Delete для этой ссылки:
this.HasMany(x => x.Communications)
.AsSet()
.KeyColumn("PersonCompanyId")
.Fetch.Select()
.Inverse()
.Cascade.Delete();
Но когда я сейчас выполню следующий HQL-запрос:
var sql = "delete from PersonCompany where Person.Id in (:idList) or Company.Id in (:idList)";
с
var query = NHibernateHelper.CurrentSession.CreateQuery(sql);
query.SetParameterList("idList", contactIdList);
query.SetTimeout(0);
query.ExecuteUpdate();
Я всегда получаю это SqlException:
Оператор DELETE конфликтует с ограничением REFERENCE "FK_PersonCompany_Communication". Конфликт произошел в базе данных "proconact", таблице "dbo.Communication", столбце "PersonCompanyId". Заявление было прекращено.
Я думаю, что NHibernate теперь должен удалить каскад ссылочных записей в коммуникации - не так ли?
Я надеюсь, что кто-то может мне помочь, что я делаю неправильно.
2 ответа
Синтаксис, который вы использовали, на самом деле является частью
которые фактически используются для BULK операции на сервере БД. Они используют синтаксис HQL, но не охватывают каскад (потому что они не выполняются в памяти, только на стороне БД)
Таким образом, мы можем загрузить объекты, которые будут удалены... и явно удалить их. Это вызовет каскады:
//var sql = "delete from PersonCompany where Person.Id in (:idList) or Company.Id in (:idList)";
var sql = "from PersonCompany where Person.Id in (:idList) or Company.Id in (:idList)";
var query = NHibernateHelper.CurrentSession.CreateQuery(sql);
query.SetParameterList("idList", contactIdList);
query.SetTimeout(0);
//query.ExecuteUpdate();
var list = query.List<PersonCompany >();
foreach (var item in list)
{
session.Delete(item);
}
session.Flush();
Случилось так, что каждый элемент должен быть удален и помещен в ISession
, В течение Delete()
все каскады были правильно выполнены
Способ сделать это,
IList<PersonCompany> _pCompanies = ....; <load the required person companies>
foreach (var pc in _pCompanies)
{
_session.delete(pc);
}
потому что когда вы используете массовые обновления, встроенные ограничения не будут работать в Nhibernate. Вы можете попытаться создать ограничение уровня БД.