使用NHibernate插入带有复合键的记录

时间:2009-06-15 06:04:12

标签: c# .net nhibernate composite-id

我正在使用使用复合键的旧数据库。我正在尝试使用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列会自动递增。

是否可以编写某种处理程序,允许我使用ID集创建CountryId对象,并让它自动增加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>

4 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

或许这可能有效。如果您明确添加更新语句,另外如果您需要将其更改为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>

答案 2 :(得分:0)

我知道你不能改变数据库表或约束,但是你绝对确定数据库对象真的暗示你必须使用NHibernate复合键吗?

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

也许主要关键因为其他原因而被同事放在那里(索引等)。

这意味着你的NHibernate映射应该真正崩溃到一个非常简单的东西:一个普通的POCO,使用一个简单的NHibernate本机id生成器将一个ID映射到tablename_id。然后,CountryID属性将您的ellided属性作为普通属性加入以实现您的目标: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>

答案 3 :(得分:0)

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

Map(x =&gt; x.Field).Column(&#34; Field&#34;)。Generated.Always()。ReadOnly();