1

我有一个表格定义,如下所示:

执照

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 进行更新。

类似于:Update License SET Used=Used-1 WHERE ClientId='xxx' AND Type=1

请帮忙。

谢谢, 马赫什

4

3 回答 3

3

您必须使用复合 ID

http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-compositeid

于 2010-05-11T16:23:03.723 回答
2

如果您的主键是复合键,则您的映射应该反映这一点,并且您的类需要覆盖Equalsand GetHashCode

此外,如果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>
于 2010-05-11T16:54:02.120 回答
1

正如上面提到的其他同志,您必须使用复合ID,这不是最佳但可以接受的做法。

另一方面,您可以简单地编写一个更新拦截器并确保其中的 Type = 1。

以下是有关该主题的一些链接,可帮助您清楚地了解这一点。

  1. 优雅的代码:实现 NHibernate 拦截器
  2. NHibernate 文档:拦截器
  3. 示例 NHibernate IInterceptor 实现
  4. 企业 .NET 社区:NHibernate 第 2 部分(向下滚动到:拦截器和持久生命周期
  5. NHibernate 拦截器审计插入的对象 ID(SO 问题)

在复合键上使用拦截器的主要优点是它不会破坏您的 DBRM 并提供绝对更灵活的解决方案,而不会“污染”您的映射文件,这将更准确地表示您的模型。

于 2010-05-11T17:07:19.973 回答