问题
I have a table Communication which has a reference to PersonCompany. In the mapping for PersonCompany i have defined a Cascade-Delete for this reference:
this.HasMany(x => x.Communications)
.AsSet()
.KeyColumn("PersonCompanyId")
.Fetch.Select()
.Inverse()
.Cascade.Delete();
But when I now execute the fallowing HQL-Query:
var sql = "delete from PersonCompany where Person.Id in (:idList) or Company.Id in (:idList)";
with
var query = NHibernateHelper.CurrentSession.CreateQuery(sql);
query.SetParameterList("idList", contactIdList);
query.SetTimeout(0);
query.ExecuteUpdate();
I always get this SqlException:
The DELETE statement conflicted with the REFERENCE constraint "FK_PersonCompany_Communication". The conflict occurred in database "proconact", table "dbo.Communication", column 'PersonCompanyId'. The statement has been terminated.
I think, NHibernate should now delete cascade the referenced records in Communication - should'nt it?
I hope someone can help me, what I am doing wrong.
回答1:
The syntax you've used is in fact part of the
- 13.3. DML-style operations,
which are in fact used to BULK operation on the DB server. They use the HQL syntax, but do not cover the cascade (because they are not executed in memory, just on the DB side)
This way, we can load the objects, to be deleted... and explicitly delete them. This will trigger cascades:
//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();
What happened is, that each and every item to be deleted, and placed in ISession
. During the Delete()
all the cascades were properly executed
- 9.9. Lifecyles and object graphs
回答2:
way to do is,
IList<PersonCompany> _pCompanies = ....; <load the required person companies>
foreach (var pc in _pCompanies)
{
_session.delete(pc);
}
because when you use bulk updates, built in constraints is not going to work in Nhibernate. You could try to create a DB level constraint.
来源:https://stackoverflow.com/questions/24477039/delete-cascade-is-not-working-with-nhibernate