使用复合键的NHibernate更新

时间:2010-05-11 16:13:59

标签: asp.net nhibernate composite-key

我有一个表格定义如下:

许可证

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

请帮忙。

谢谢, 马赫什

3 个答案:

答案 0 :(得分:3)

答案 1 :(得分:2)

如果您的主键是复合键,那么您的映射应该反映出来,并且您的类需要覆盖EqualsGetHashCode

此外,如果ClientIdClient实体的主键,则应将其映射为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。

以下是有关此主题的一些链接,可帮助您了解此内容。

  1. Elegant code : Implementing NHibernate Interceptors
  2. NHibernate Documentation : Interceptors
  3. Sample NHibernate IInterceptor implementation
  4. Enterprise .NET Community : NHibernate Part 2(向下滚动到:拦截器和持久生命周期
  5. NHibernate Interceptor Auditing Inserted Object Id(问题)
  6. 在复合键上使用拦截器的主要优点是它不会破坏您的DBRM并提供一个绝对更灵活的解决方案,而不会“污染”您的映射文件,这将更精确地代表您的模型。