我一直在关注 NHibernate 之夏系列。到目前为止一切顺利,一切都按预期工作,即使我使用的是 NHibernate 3.1 并且视频使用版本 1.2。
但是,我刚刚遇到了一个问题,对我来说这似乎是一个巨大的错误。我现在正在进行第 3 场 session ,我们将在数据库中插入、更新和删除客户。这是客户类:
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 的这种奇怪行为是否正常,或者我是否必须做一些特殊的事情才能让它按照我期望的方式工作,但对我来说,它看起来像一个错误。
最佳答案
从 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() 调用隐式地为您刷新 session (当然,假设您没有修改 FlushMode 的默认设置)。
关于nhibernate - NHibernate 3.1 坏了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6171682/