У меня есть схема (поля не обязательны):
занятой кот http://picsearch.ru/share/image-BCE8_4E168F3B.jpg
У меня есть сопоставления:
Entity
<class name="LogicalModel.Entity" table="`Entity`" lazy="true">
<id name="Id" ..> ... </id>
<bag name="Attributes" lazy="true" cascade="all-delete-orphan" fetch="select" batch-size="1" access="property" inverse="true">
<key column="`Entity`" />
<one-to-many class="LogicalModel.Attribute" />
</bag>
<bag name="Keys" lazy="true" cascade="all-delete-orphan" fetch="select" batch-size="1" access="property" inverse="true">
<key column="`Entity`" />
<one-to-many class="LogicalModel.Key" />
</bag>
</class>
Атрибут
<class name="LogicalModel.Attribute" table="`Attribute`" lazy="true">
<id name="Id" ..> ... </id>
<many-to-one name="Type" class="LogicalModel.Entity" column="`Type`" cascade="save-update" fetch="select" not-null="true" foreign-key="fk_TypeAttribute" />
<many-to-one name="Entity" class="LogicalModel.Entity" column="`Entity`" cascade="none" fetch="select" not-null="true" foreign-key="fk_EntityAttributes" />
</class>
ключ
<class name="LogicalModel.Key" table="`Key`" lazy="true">
<id name="Id" ..> ... </id>
<bag name="KeyAttributes" lazy="true" cascade="all-delete-orphan" fetch="select" access="property" inverse="true">
<key column="`Key`" />
<one-to-many class="LogicalModel.KeyAttribute" />
</bag>
<many-to-one name="Entity" class="LogicalModel.Entity" column="`Entity`" cascade="none" fetch="select" not-null="true" foreign-key="fk_EntityKeys" />
</class>
KeyAttribute:
<class name="LogicalModel.KeyAttribute" table="`KeyAttribute`" lazy="false">
<id name="Id" ..> ... </id>
<many-to-one name="Attribute" class="LogicalModel.Attribute" column="`Attribute`" cascade="save-update" fetch="select" not-null="true" foreign-key="fk_AttributeKeyAttribute" />
<many-to-one name="Key" class="LogicalModel.Key" column="`Key`" cascade="none" fetch="select" not-null="true" foreign-key="fk_KeyKeyAttributes" />
</class>
Теперь, пожалуйста, посмотрите ...
Как видите, у нас есть односторонняя основная ассоциация KeyAttribute - атрибут , так что это просто много-к-одному, и мне вообще не нужна обратная связь.
Теперь проблема в том, что я пытаюсь удалить весь график - удалить объект Entity (обратите внимание: Entity на самом деле вообще не загружаются, это просто набор прокси, поэтому NHibernate делает дополнительный SELECT запросы на проверку ссылок перед удалением)
как это
Session.Delete(Entity); // here PropertyValueException:
// not-null property references a null or transient value: LogicalModel.KeyAttribute.Attribute
Session.Flush(); // Actually I use transactions in my code, but don't mind
SQL Profiler:
exec sp_executesql N'SELECT entities0_.[Id] as Id1_1_, entities0_.[Id] as Id1_45_0_,
FROM [Entity] entities0_ WHERE entities0_.[LogicalModel]=@p0',N'@p0 uniqueidentifier',@p0='DC8F8460-9C41-438A-8334-97D0A94E2528'
exec sp_executesql N'SELECT attributes0_.[Entity] as Entity12_1_, attributes0_.[Id] as Id1_1_, attributes0_.[Id] as Id1_16_0_, attributes0_.[Type] as Type11_16_0_, attributes0_.[Entity] as Entity12_16_0_
FROM [Attribute] attributes0_ WHERE attributes0_.[Entity]=@p0',N'@p0 uniqueidentifier',@p0='63E4D568-EAB2-4DF2-8FED-014C8CB2DE22'
exec sp_executesql N'SELECT keys0_.[Entity] as Entity4_1_, keys0_.[Id] as Id1_1_, keys0_.[Id] as Id1_43_0_, keys0_.[Entity] as Entity4_43_0_
FROM [Key] keys0_ WHERE keys0_.[Entity]=@p0',N'@p0 uniqueidentifier',@p0='63E4D568-EAB2-4DF2-8FED-014C8CB2DE22'
exec sp_executesql N'SELECT keyattribu0_.[Key] as Key4_1_, keyattribu0_.[Id] as Id1_1_, keyattribu0_.[Id] as Id1_0_0_, keyattribu0_.[Attribute] as Attribute3_0_0_, keyattribu0_.[Key] as Key4_0_0_
FROM [KeyAttribute] keyattribu0_ WHERE keyattribu0_.[Key]=@p0',N'@p0 uniqueidentifier',@p0='103D8FB3-0B17-4F51-8AEF-9623616AE282'
Итак, что мы можем увидеть:
свойство not-null ссылается на нулевое или временное значение: LogicalModel.KeyAttribute.Attribute
произошло сразу после проверки поля NH Атрибут (нет-нулевое ограничение в БД, все в порядке) в классе KeyAttribute (см. журнал профилировщика).
Это довольно забавно, потому что NH должен удалить оба атрибута и KeyAttributes, NH читает информацию о поле Attribute в классе KeyAttribute, FOUND это в БД, NOT FOUND это в NH session (!!!) (потому что Атрибуты были загружены раньше), и просто выбросьте эту глупую ошибку.
Что я уже пытался сделать:
1. make not-null = "false". В этом случае NH делает дополнительное обновление - попробуйте установить Attribute = NULL - вызвать нарушение ограничения в БД.
2. установить lazy = "false", lazy = "no-proxy" для связи многие-к-одному для KeyAttribute-Attribute - ничего;
Теперь мне не нравится идея перехватчиков, потому что во многих ситуациях у меня такая же ситуация, мне нужно общее решение
Пожалуйста, ребята, есть предложения?