5

我正在使用一个使用复合键的旧数据库。我正在尝试使用 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

4 回答 4

0

perhaps this may work. If you add the update statement explicitly, Also if you need to change it to a sProc or something like that you can.

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

here is an example of the sproc concept.

<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>
于 2009-06-16T11:27:47.383 回答
0

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

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

于 2009-06-15T07:57:31.007 回答
0

我知道您无法更改数据库表或约束,但是您绝对确定数据库对象真的暗示您必须使用 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>
于 2009-09-09T09:45:54.623 回答
0

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

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

于 2014-07-07T21:34:57.207 回答