当我这样做时:
Cat x = Session.Load<Cat>(123);
x.Name = "fritz";
Session.Flush();
NHibernate检测到更改并更新数据库。但是,当我这样做时:
Cat x = new Cat();
Session.Save(x);
x.Name = "fritz";
Session.Flush();
我的名字为NULL,因为当我打电话给Session.Save()
时就是这样。为什么NHibernate没有检测到更改 - 或者更好的是,在Flush()
时采用INSERT语句的值?
已添加:澄清:Session.FlushMode
设置为None
,因此在我这样说之前没有自动刷新。我也在使用GUID主键(使用guid.comb生成器)。
我这样做的原因是因为我使用Session作为“肮脏”的跟踪器。我正在编写一个Windows窗体应用程序,我的每个窗体都有一个单独的会话,只要表单一样长。会话尽可能保持断开连接,这样我就不会用完ADO.NET连接(它是一个MDI应用程序,并且没有限制可以打开多少表单)。每个表单还有一个“确定”按钮和一个“取消”按钮。 “确定”按钮调用Session.Flush()
然后关闭表单; “取消”按钮只关闭表单并静默地丢弃用户所做的所有更改。
嗯,至少那是我想要的。上面的错误给了我一些问题。
答案 0 :(得分:0)
除非你有充分的理由不这样做,否则你必须使用交易而不是明确的同花顺电话。
using (var session = createSession())
{
using (var transaction = session.BeginTransaction())
{
Cat x = new Cat();
session.Save(x);
x.Name = "fritz";
try
{
transaction.Commit();
}
catch
{
// prevents your database from getting corrupt when you have a bug
transaction.RollBack();
throw;
}
}
}
在实际应用程序中,最好将事务创建,提交和回滚隐藏在应用程序的单独部分中,这样您就不必在每个数据访问块中调用它。在具有关系数据库的大多数应用程序中,一个事务围绕处理用户的一个屏幕的整个代码。这会导致用户所做的所有操作成功,或者在存在错误时失败,作为原子块。用户在屏幕上更改的所有数据都会被存储,或者不会存储任何内容,也不会存储任何数据。
答案 1 :(得分:0)
NHibernate会跟踪更改,但是您编写的代码将导致它在调用Save时发出一个带有值的插入,并在调用Save后对更改进行更新。 Save使对象持久化(插入),然后NHibernate开始跟踪对持久对象(更新)所做的更改。刷新会话时都会提交插入和更新。
我们的Windows窗体应用程序面临着类似的问题,我认为我们将采取不同的方法。 FlushMode保留为Auto(默认),如果用户取消操作,则会从会话中逐出对象(ISession.Evict)。驱逐对象使其成为瞬态,这正是所期望的行为。