Вставка записи с помощью составного ключа с помощью NHibernate - PullRequest
5 голосов
/ 15 июня 2009

Я работаю с устаревшей базой данных, которая использует составные ключи. И я пытаюсь использовать NHibernate, чтобы вставить новую запись в базу данных. NHibernate указывает, что я должен создать 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 ]

0 голосов
/ 16 июня 2009

возможно, это может сработать. Если вы добавите оператор 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 голосов
/ 09 сентября 2009

Я понимаю, что вы не можете изменить таблицу базы данных или ограничения, но вы абсолютно уверены, что объекты базы данных действительно подразумевают, что вы должны использовать составной ключ NHibernate?

Составной ключ NHibernate следует использовать для тех таблиц, в которых уникальность строки определяется более чем одним столбцом. В приведенном вами примере выясняется, что уникальность каждой строки фактически определяется только одним столбцом tablename_id. Первичный ключ оказывается излишним: его нельзя нарушить, поскольку один из его составных элементов - это столбец идентификаторов, который всегда будет другим.

Возможно, ваш коллеги разместили первичный ключ по какой-то другой причине (индексация и т. Д.).

Это означает, что ваше сопоставление NHibernate должно действительно свернуть во что-то довольно простое: обычное POCO с отображением одного идентификатора в tablename_id с использованием простого генератора собственных идентификаторов NHibernate. Свойство CountryID затем объединяет ваши свойства со знаком как обычное свойство для достижения вашей цели: CountryID устанавливается с идентификатором, автоматически увеличивающимся базой данных.

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 голосов
/ 15 июня 2009

Думаю, вы можете установить в столбце идентификаторов один из ваших ключей в составном ключе.

я знаю, что в fluentnhibernate у меня есть имя столбца идентификатора для закрытого ключа

...