NHibernate 3.1 не работает? - PullRequest
2 голосов
/ 30 мая 2011

Я следил за сериалом «Лето NHibernate». Пока все хорошо, все работает как положено, хотя я использую NHibernate 3.1, а видео использует версию 1.2.

Однако я только что столкнулся с проблемой, и мне кажется, что это ОГРОМНАЯ ошибка. Сейчас я на Сессии № 3, где мы вставляем, обновляем и удаляем клиентов из базы данных. Вот класс Клиента:

public class Customer
{
    private int customerId;
    private string firstName;
    private string lastName;

    public virtual int CustomerId
    {
        get { return customerId; }
        set { customerId = value; }
    }

    public virtual string FirstName 
    {
        get { return firstName; }
        set { firstName = value; }
    }

    public virtual string LastName
    {
        get { return lastName; }
        set { lastName = value; }
    }
}

А вот файл сопоставления:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DataTransfer" assembly="DataTransfer">
  <class name="DataTransfer.Customer, DataTransfer" table="Customer">
    <id name="CustomerId" column="CustomerId" type="Int32" unsaved-value="0">
      <generator class="native"></generator>
    </id>
    <property name="FirstName" column="FirstName" type="string" length="50" not-null="false" />
    <property name="LastName" column="LastName" type="string" length="50" not-null="false" />
  </class>
</hibernate-mapping>

Файл конфигурации ничего особенного:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="connection.driver_class">NHibernate.Driver.OdbcDriver</property>
    <property name="connection.connection_string">Dsn=datasource;uid=user</property>
    <property name="dialect">NHibernate.Dialect.MySQLDialect</property>
    <property name="show_sql">true</property>
    <mapping assembly="DataTransfer"></mapping>
  </session-factory>
</hibernate-configuration>

Теперь вот проблема. Когда я вставляю нового Клиента, вот так:

public int AddCustomer(Customer customer)
{
    int newId = (int)session.Save(customer);
    session.Flush();

    return newId;
}

newId ВСЕГДА будет равен нулю, а customer.Id никогда не обновляется до значения идентификатора, сгенерированного базой данных, даже если оператор вставки был успешным, как я вижу нового клиента в базе данных. Это происходит, когда я использую NHibernate 3.1

Но, если я изменю ссылки моего проекта на NHibernate 1.2 без изменения одной строки кода, newId будет содержать фактический вставленный Id и customer.Id будет обновлен.

Мне было интересно, нормальное ли это странное поведение NHibernate 3.1, или я должен сделать что-то особенное, чтобы оно работало так, как я ожидаю, но для меня это похоже на ошибку.

1 Ответ

3 голосов
/ 30 мая 2011

Начиная с NHibernate 2.1.2, вы должны обернуть все взаимодействия с базой данных (даже запросы) в явную транзакцию NHibernate. Есть сложный список крайних случаев, которые делают это так, но пока просто поверьте, что это так. Из-за этого типичный шаблон, который вы должны использовать здесь для этого примера, должен выглядеть аналогично следующему фрагменту:

public int AddCustomer(Customer customer)
{
    int newId;

    using(var tx = session.BeginTransaction())
    {
        newId = (int)session.Save(customer);
        tx.Commit();
    }

    return newId;
}

До NH 2.1.2 NH предоставлял неявные транзакции, если вы не указали о них явно, но, конечно, в соответствии с NH 3.1 необходимо, чтобы вы были явными относительно границ транзакции NH. Обратите внимание, что в приведенном выше примере вызов tx.Commit () неявно сбрасывает сеанс для вас (конечно, при условии, что вы не изменили настройку по умолчанию для FlushMode).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...