NHibernate Session.Flush()在未发生更新时发送更新查询

Mar*_*ski 34 .net c# nhibernate

我有一个NHibernate会话.在这个会话中,我正在执行1个操作,即运行此代码以获取列表:

public IList<Customer> GetCustomerByFirstName(string customerFirstName)
{
return _session.CreateCriteria(typeof(Customer))
    .Add(new NHibernate.Expression.EqExpression("FirstName", customerFirstName))
    .List<Customer>();
}
Run Code Online (Sandbox Code Playgroud)

我打电话Session.Flush()到最后HttpRequest,我得到了一个HibernateAdoException.NHibernate将更新语句传递给db,并导致外键违规.如果我不运行flush,请求完成没有问题.这里的问题是,如果在其他会话中发生更改,我需要刷新,因为此代码在其他区域中重用.是否有其他配置设置我可能会丢失?


这是异常的代码:

[SQL: UPDATE CUSTOMER SET first_name = ?, last_name = ?, strategy_code_1 = ?, strategy_code_2 = ?, strategy_code_3 = ?, dts_import = ?, account_cycle_code = ?, bucket = ?, collector_code = ?, days_delinquent_count = ?, external_status_code = ?, principal_balance_amount = ?, total_min_pay_due = ?, current_balance = ?, amount_delinquent = ?, current_min_pay_due = ?, bucket_1 = ?, bucket_2 = ?, bucket_3 = ?, bucket_4 = ?, bucket_5 = ?, bucket_6 = ?, bucket_7 = ? WHERE customer_account_id = ?]
Run Code Online (Sandbox Code Playgroud)

没有参数显示为传递.

zvo*_*kov 45

处理NHibernate时务必小心使用NULLable字段.如果您的字段在DB中为NULL,请确保相应的.NET类也使用Nullable类型.否则,会发生各种奇怪的事情.症状通常是NHibernate将尝试更新DB中的记录,即使您从数据库中读取实体后没有更改任何字段.

以下序列解释了为什么会发生这种情

  1. NHibernate使用ADO.NET从DB检索原始实体的数据
  2. NHibernate构造实体并设置其属性
  3. 如果DB字段包含NULL,则该属性将设置为其类型的默认值:
    • 引用类型的属性将设置为null
    • 整数和浮点类型的属性将设置为0
    • 布尔类型的属性将设置为false
    • DateTime类型的属性将设置为DateTime.MinValue
    • 等等
  4. 现在,当提交事务时,NHibernate会将该属性的值与它从DB读取的原始字段值进行比较,并且由于该字段包含NULL但该属性包含非null值,因此NHibernate将该属性视为脏,并强制更新恩赐.

这不仅会损害性能(每次检索实体时,您都会获得额外的数据库往返和额外更新),但这也可能导致很难对DateTime列的错误进行故障排除.实际上,当DateTime属性初始化为其默认值时,它设置为1/1/0001.当此值保存到DB时,ADO.NET的SqlClient无法将其转换为有效的SqlDateTime值,因为可能的最小SqlDateTime是1/1/1753!

最简单的解决方法是使类属性使用Nullable类型,在本例中为"DateTime?".或者,您可以通过实现IUserType及其Equals方法来正确地比较DbNull.Value与值类型的任何默认值来实现自定义类型映射器.在我们的例子中,当将1/1/0001与DbNull.Value进行比较时,Equals需要返回true.实现一个全功能的IUserType并不是那么难,但它确实需要NHibernate琐事的知识,所以如果你选择这样做,准备做一些实质性的谷歌搜索.


Rya*_*eld 16

我之前看过一次,当我的一个模型没有正确映射时(没有正确使用可空类型).请你贴上你的模型和贴图吗?