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.

米国の本社が管理しているため、データベースの設定に触れることはできません。

次の方法でdb挿入を実行できることがわかりました。

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

おそらくこれはうまくいくかもしれません。update ステートメントを明示的に追加する場合、また、それを 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>
于 2009-06-16T11:27:47.383 に答える
0

fluent nhibernate auto increment non key (Id) propertyに記載されているように、フィールドの生成された性質を取得するために複合キーを使用する必要がない場合があります。これまたは次のようなものを使用することを検討してください。

Map(x => x.Field).Column("フィールド").Generated.Always().ReadOnly();

于 2014-07-07T21:34:57.207 に答える
0

データベース テーブルや制約を変更できないことは理解していますが、データベース オブジェクトが、NHibernate 複合キーを使用する必要があることを本当に意味していると確信していますか?

行の一意性が複数の列によって決定されるテーブルには、NHibernate 複合キーを使用する必要があります。あなたが提供した例では、各行の一意性は実際には単一の tablename_id 列によってのみ決定されることがわかりました。主キーは不要であることが判明しました。つまり、その構成要素の 1 つが ID 列であり、常に異なるため、違反することはできません。

他の理由 (索引付けなど) で、主キーが同僚によってそこに配置されている可能性があります。

これは、NHibernate マッピングが非常に単純なものに崩壊する必要があることを意味します。単純な NHibernate ネイティブ ID ジェネレーターを使用して tablename_id にマッピングされる単一の 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 に答える