2009-06-15 10 views
5

Pracuję ze starszą bazą danych, która używa kluczy złożonych. Próbuję użyć NHibernate do wstawienia nowego rekordu do bazy danych. NHibernate określa, że ​​muszę ręcznie utworzyć identyfikator, ale gdy próbuję wstawić z tym ID otrzymuję komunikat:Wstawianie rekordu za pomocą klucza złożonego przy użyciu NHibernate

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

nie mogę dotykać ustawieniami db jak są one podawane przez siedzibą w USA.

odkryłem, że mogę zrobić wkładkę db poprzez:

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

a kolumna jest automatycznie zwiększany tablename_id.

Czy jest możliwe napisanie jakiegoś programu obsługi, który pozwala mi utworzyć obiekt ID za pomocą zestawu CountryId i automatycznie zwiększyć jego właściwość Id.

Pozdrawiam.


Przykład Kod:

Tabela Definicja:

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

klasy plików:

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

Mapowanie plików

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

Odpowiedz

0

Myślę, że możesz ustawić kolumnę tożsamości dla jednego z kluczy w kluczu złożonym.

wiem, że w FluentNhibernate mam nazwę kolumny tożsamości dla omposite klucz

+0

Jak to wpłynie na buforowanie obiektów? W szczególności 'session.Get (id);' z możliwością duplikacji w kolumnie 'tablename_id'. – zonkflut

+0

ta opcja powoduje, że wyjątek FKUnmatchingColumnsException "musi mieć taką samą liczbę kolumn, jak odwoływany klucz podstawowy" – zonkflut

0

może ten może pracować. Jeśli dodasz jawnie instrukcję aktualizacji, również jeśli chcesz ją zmienić na sProc lub coś podobnego, możesz.

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

tutaj jest przykładem koncepcji 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

Rozumiem, że nie można zmieniać tabeli bazy danych lub ograniczenia, ale jesteś absolutnie pewien, że obiekty bazy danych wynika, że ​​naprawdę trzeba użyć klucza kompozytowego NHibernate?

Klucz NHibernate Composite powinien być używany w tych tabelach, w których unikalność rzędu jest określona przez więcej niż jedną kolumnę. W podanym przykładzie okazało się, że unikalność każdego wiersza jest faktycznie określona tylko przez pojedynczą kolumnę tablename_id. Klucz podstawowy okazuje się zbędny: to znaczy, nie można go naruszyć, ponieważ jednym z jego elementów składowych jest kolumna tożsamości, która zawsze będzie inna.

Być może klucz podstawowy został tam umieszczony przez twoich współpracowników z jakiegoś innego powodu (indeksowania itp.).

Oznacza to, że mapowanie NHibernate powinno naprawdę zapaść w coś bardzo prostego: normalne POCO z pojedynczym odwzorowaniem identyfikatora na tablename_id przy użyciu prostego natywnego generatora NHibernate. Właściwość CountryID następnie dołącza do ellowanych właściwości jako normalna właściwość do osiągnięcia celu: Identyfikator Country jest ustawiany z identyfikatorem automatycznie zwiększanym przez bazę danych.

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

Identyfikator krajowy jest wymagany, ponieważ służy do jednoznacznej identyfikacji, która instancja bazy danych (tj. Baza danych tego kraju) znajduje się w replikacji. To było oryginalne rozwiązanie wybrane do obsługi rozproszonych baz danych. Dlatego, aby zachować poprawność, muszę użyć klucza złożonego :( – zonkflut

Powiązane problemy