我有一个表格定义如下:
ClientId
Type
Total
Used
ClientId和Type一起唯一标识一行。我有一个映射文件,如下所示:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="Acumen.AAM.Domain.Model.License, Acumen.AAM.Domain" lazy="false" table="License">
<id name="ClientId" access="field" column="ClientID" />
<property name="Total" access="field" column="Total"/>
<property name="Used" access="field" column="Used"/>
<property name="Type" access="field" column="Type"/>
</class>
</hibernate-mapping>
如果客户端使用许可证创建用户,我需要更新表中的Used列。当我在映射xml中将ClientId列设置为此表的id列时,我收到TooManyRowsAffectedException。
请告诉我如何在映射级别设置复合键,以便NHibernate可以根据ClientId和Type进行更新。
类似:更新许可证SET已使用=已使用-1 WHERE ClientId ='xxx'AND Type = 1
请帮忙。
谢谢, 马赫什
答案 0 :(得分:3)
答案 1 :(得分:2)
如果您的主键是复合键,那么您的映射应该反映出来,并且您的类需要覆盖Equals
和GetHashCode
。
此外,如果ClientId
是Client
实体的主键,则应将其映射为many-to-many
,而不仅仅是ID。
另外,为什么要指定lazy="false"
?你知道这些影响吗?
另外,为什么用access="field"
映射所有内容?属性是否有一些特殊的逻辑?
考虑到我刚写的所有内容,这是一个修改后的映射。请随意忽略那些不适用的部分: - )
<class name="Acumen.AAM.Domain.Model.License, Acumen.AAM.Domain" table="License">
<composite-id>
<key-many-to-one name="Client" column="ClientID" />
<key-property name="Type" />
</composite-id>
<property name="Total" />
<property name="Used" />
</class>
答案 2 :(得分:1)
正如上面提到的其他同志一样,你必须使用复合身份证,这不是一个最好但可以接受的做法。
另一方面,你可以简单地写一个update interceptor并确保你的Type = 1。
以下是有关此主题的一些链接,可帮助您了解此内容。
在复合键上使用拦截器的主要优点是它不会破坏您的DBRM并提供一个绝对更灵活的解决方案,而不会“污染”您的映射文件,这将更精确地代表您的模型。