2009-06-15 73 views
5

我正在使用使用複合鍵的遺留數據庫。我正在嘗試使用NHibernate將新記錄插入到數據庫中。 NHibernate的規定,我必須手動創建標識,但是當我試圖用這個ID來插入我得到的消息:使用NHibernate插入帶複合鍵的記錄

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> 

回答

0

我認爲您可以將標識列設置爲組合鍵中的其中一個鍵。

我知道,在我fluentnhibernate爲omposite關鍵

+0

這會如何影響緩存對象?特別是`session.Get (id);`可能在`tablename_id`列中有重複。 – zonkflut 2009-06-16 00:29:10

+0

此選項將引發FKUnmatchingColumnsException'必須具有與引用的主鍵相同的列數' – zonkflut 2009-06-16 06:02:43

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

我明白,你不能改變數據庫表或約束,但你絕對確保數據庫對象真的意味着你必須使用一個NHibernate的複合鍵?

NHibernate複合鍵應該用於那些行唯一性由多個列確定的表。在您提供的示例中,每個行的唯一性實際上僅由單個tablename_id列確定。主鍵原來是多餘的:也就是說,它不能被侵犯,因爲它的組成元素之一是一個標識列,它總是不同的。

也許主鍵已被您的同事放置在那裏由於其他原因(索引等)。

這意味着你的NHibernate映射應該真的摺疊成一個非常簡單的東西:一個普通的POCO,它使用一個簡單的NHibernate本地id生成器,映射到tablename_id。然後,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>