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

发布于 2024-07-25 09:44:59 字数 1909 浏览 10 评论 0原文

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

I am working with a legacy database that uses composite keys. And I am trying to use NHibernate to insert a new record into the database. NHibernate specifies that I have to create the Id manually, but when I try to insert with this id I get the message:

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

I cannot touch any of the db settings as they are administered by head office in USA.

I found that I can do a db insert via:

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

and the tablename_id column is automatically incremented.

Is it possible to write some sort of a handler that allows me to create an ID object with the CountryId set and have it auto-increment the Id property.

Cheers.

Example Code:

Table Definition:

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
    )
)

Class Files:

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(); } }
}

Mapping File:

<?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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

森林很绿却致人迷途 2024-08-01 09:44:59

我认为您可以将身份列设置为复合键中的键之一。

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

I Think you can set an identity column to one of your keys in the composite key.

i know that in fluentnhibernate i have a identity column name for a omposite key

鲜血染红嫁衣 2024-08-01 09:44:59

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

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

这是存储过程概念的一个示例。

<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>

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>
岁月如刀 2024-08-01 09:44:59

我知道您不能更改数据库表或约束,但是您绝对确定数据库对象确实意味着您必须使用 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>

I understand that you cannot alter the database table or constraints, but are you absolutely sure that the database objects really imply that you have to use an NHibernate composite key?

An NHibernate composite key should be used for those tables where the uniqueness of a row is determined by more than one column. In the example that you provided in turns out that the each row's uniqueness is actually only determined by the single tablename_id column. The primary key turns out to be superfluous: that is, it cannot be violated because one of its constituent elements is an identity column which will always be different.

Perhaps the primary key has been placed there by your colleagues for some other reason (indexing etc.).

This means that your NHibernate mapping should really collapse to something quite simple: a normal POCO with a single ID mapping to tablename_id using a simple NHibernate native id generator. The CountryID property then joins your ellided properties as a normal property to achive your aim: CountryID is set with ID auto-incremented by the database.

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>
最初的梦 2024-08-01 09:44:59

as noted in fluent nhibernate auto increment non key (Id) property, it may not be necessary to use a composite key to get the generated nature of the field. Consider using this or similar to:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文