【问题标题】:Inserting a record with a Composite Key using NHibernate使用 NHibernate 插入带有复合键的记录
【发布时间】:2010-11-02 22:33:04
【问题描述】:

我正在使用一个使用复合键的旧数据库。我正在尝试使用 NHibernate 将新记录插入数据库。 NHibernate 指定我必须手动创建 Id,但是当我尝试使用此 id 插入时,我收到消息:

System.Data.SqlClient.SqlException: Cannot insert explicit value for identity column in table 'tablename' when IDENTITY_INSERT is set to OFF.

我无法触摸任何数据库设置,因为它们由美国总部管理。

我发现我可以通过以下方式进行数据库插入:

insert into tablename (tablename_country_id, /*extra fields here*/) values (16, /*extra values here*/)

tablename_id 列会自动递增。

是否可以编写某种处理程序,允许我创建一个带有CountryId 集的ID 对象,并让它自动增加Id 属性。

干杯。


示例代码:

表定义:

CREATE TABLE [dbo].[tablename](
    [tablename_country_id] [int] NOT NULL,
    [tablename_id] [int] IDENTITY(1,1) NOT NULL,

    -- more fields here

    CONSTRAINT [pk_tablename] PRIMARY KEY
    (
        [tablename_country_id] ASC,
        [tablename_id] ASC
    )
)

类文件:

public class ModelObject
{
    public ID { get; set; }
    // more properties here
}

public class ID : INHibernateProxy
{
    public int Id { get; set; }
    public int CountryId { get; set; }
    public ILazyInitializer HibernateLazyInitializer { get { throw new ApplicationException(); } }
}

映射文件:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Model" assembly="API">
    <class name="ModelObject" table="dbname.dbo.tablename" lazy="false">
        <composite-id name="Id" class="ID">
            <key-property name="Id" column="tablename_id" type="int" />
            <key-property name="CountryId" column="tablename_country_id" type="int" />
        </composite-id>
        <!-- more properties here -->
    </class>
</hibernate-mapping>

【问题讨论】:

    标签: c# .net nhibernate composite-id


    【解决方案1】:

    我认为您可以将标识列设置为复合键中的一个键。

    我知道在 fluentnhibernate 中我有一个组合键的标识列名称

    【讨论】:

    • 这会如何影响对象的缓存?特别是 session.Get&lt;TModel&gt;(id); 可能在 tablename_id 列中出现重复。
    • 这个选项抛出一个 FKUnmatchingColumnsException 'must have the same number of columns as the referenced primary key'
    【解决方案2】:

    也许这可能有效。如果您显式添加更新语句,并且如果您需要将其更改为 sProc 或类似的东西,您可以。

    https://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/querysql.html#querysql-cud
    

    这是 sproc 概念的一个示例。

    <class name="Person">
        <id name="id">
            <generator class="increment"/>
        </id>
        <property name="name" not-null="true"/>
        <sql-insert>exec createPerson ?, ?</sql-insert>
        <sql-delete>exec deletePerson ?</sql-delete>
        <sql-update>exec updatePerson ?, ?</sql-update>
    </class>
    

    【讨论】:

      【解决方案3】:

      我了解您无法更改数据库表或约束,但您确定数据库对象确实暗示您必须使用 NHibernate 复合键吗?

      NHibernate 复合键应该用于那些行的唯一性由多个列确定的表。在您提供的示例中,每行的唯一性实际上仅由单个 tablename_id 列确定。结果证明主键是多余的:也就是说,它不能被违反,因为它的组成元素之一是一个标识列,它总是不同的。

      您的同事可能出于其他原因(索引等)将主键放在那里。

      这意味着您的 NHibernate 映射应该真正崩溃为非常简单的东西:使用简单的 NHibernate 本机 id 生成器将单个 ID 映射到 tablename_id 的普通 POCO。 CountryID 属性然后将您省略的属性作为普通属性加入以实现您的目标: CountryID 设置为 ID 由数据库自动递增。

      public class ModelObject
      {
          public int ID { get; set; }
          public int CountryID { get; set; }
          // more properties here
      }
      
      <?xml version="1.0" encoding="utf-8" ?>
      <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Model" assembly="API">
          <class name="ModelObject" table="dbname.dbo.tablename" lazy="false">
              <id name="ID" column="tablename_id" type="int">
              <generator class="native" />
          </id>
              <property name="CountryID" column="tablename_country_id" type="int" />
              <!-- more properties here -->
          </class>
      </hibernate-mapping>
      

      【讨论】:

      • CountryID 是必需的,因为它用于唯一标识正在复制的数据库实例(即哪个国家的数据库)。这是为处理分布式数据库而选择的原始解决方案。因此,为了保持正确,我必须使用复合键:(
      【解决方案4】:

      fluent nhibernate auto increment non key (Id) property 中所述,可能不需要使用复合键来获取字段的生成性质。考虑使用这个或类似的:

      Map(x => x.Field).Column("Field").Generated.Always().ReadOnly();

      【讨论】:

        猜你喜欢
        • 2019-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-10
        • 1970-01-01
        • 1970-01-01
        • 2015-01-24
        • 1970-01-01
        相关资源
        最近更新 更多