【发布时间】:2011-07-08 06:12:03
【问题描述】:
我有一个方案(字段不是必需的):
a busy cat http://picsearch.ru/share/image-BCE8_4E168F3B.jpg
我有映射:
实体
<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>
关键属性:
<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 - Attribute,所以它只是多对一,我根本不需要反向关联。
现在的问题是当我尝试删除 整个图 - 删除实体对象(注意:实体实际上根本没有加载,它只是一组代理,这就是 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 探查器:
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'
所以我们可以看到:
非空属性引用空值或瞬态值:LogicalModel.KeyAttribute.Attribute 发生在 KeyAttribute 类中的 NH 检查字段 Attribute (db 中的非空约束,没关系)之后(参见分析器日志)。
这很有趣,因为 NH 必须同时删除 Attributes 和 KeyAttributes,NH 在 KeyAttribute 类中读取有关 Attribute 字段的信息,FOUND 在 DB 中,NOT FOUND 在NH session (!!!)(因为之前加载了属性),然后抛出这个愚蠢的错误。
我已经尝试过的事情: 1. 使 not-null="false"。在这种情况下,NH 会进行额外的更新 - 尝试设置 Attribute=NULL - 导致 DB 中的约束违规。 2. 在 KeyAttribute-Attribute 的多对一关联上设置lazy="false",lazy="no-proxy" - 无;
现在我不喜欢拦截器的想法,因为在很多情况下我都有相同的情况,我需要通用解决方案
各位,有什么建议吗?
【问题讨论】:
标签: nhibernate cascade