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

时间:2020-03-05 18:45:06  来源:igfitidea点击:

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

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

我在HttpRequest的末尾调用Session.Flush(),并且得到了HibernateAdoException。 NHibernate正在将更新语句传递给数据库,并导致外键冲突。如果我不运行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 = ?]

没有参数显示为正在传递。

解决方案

回答

当我的一个模型未正确映射(未正确使用可为空的类型)时,我见过一次。我们可以粘贴模型和贴图吗?

回答

当我尝试使用access =" noop"隐藏多对多包装袋的反端时,我也在NH 2.0.1中遇到了这个问题(提示:这不起作用)。

将它们转换为access =" field" +在类上添加一个字段可解决此问题。但是,很难找到它们。

回答

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

以下顺序说明了为什么会发生这种情况:

  • NHibernate使用ADO.NET从数据库检索原始实体的数据
  • NHibernate构造实体并设置其属性
  • 整数和浮点类型的属性将设置为0
  • 布尔类型的属性将设置为false
  • DateTime类型的属性将设置为DateTime.MinValue
  • 等等。
  • 现在,提交事务后,NHibernate会将属性值与其从DB中读取的原始字段值进行比较,并且由于该字段包含NULL但该属性包含非空值,因此NHibernate认为该属性很脏,并强制进行更新的实体。

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

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