Why NHibernate updates DB on commit of read-only transaction
http://www.zvolkov.com/clog/2009/07/09/why-nhibernate-updates-db-on-commit-of-read-only-transaction/
Always be careful with NULLable fields whenever you deal with NHibernate. If your field is NULLable in DB, make sure corresponding .NET class uses Nullable type too. Otherwise, all kinds of weird things will happen. The symptom is usually will be that NHibernate will try to update the record in DB, even though you have not changed any fields since you read the entity from the database.
The following sequence explains why this happens:
- NHibernate retrieves raw entity's data from DB using ADO.NET
- NHibernate constructs the entity and sets its properties
- If DB field contained NULL the property will be set to the defaul value for its type:
- properties of reference types will be set to null
- properties of integer and floating point types will be set to 0
- properties of boolean type will be set to false
- properties of DateTime type will be set to DateTime.MinValue
- etc.
- Now, when transaction is committed, NHibernate compares the value of
the property to the original field value it read form DB, and since the
field contained NULL but the property contains a non-null value,
NHibernate considers the property dirty, and forces an update of the
enity.
Not only this hurts performance (you get
extra round-trip to DB and extra update every time you retrieve the
entity) but it also may cause hard to troubleshoot errors with DateTime
columns. Indeed, when DateTime property is initialized to its default
value it's set to 1/1/0001. When this value is saved to DB, ADO.NET's
SqlClient can't convert it to a valid SqlDateTime value since the
smallest possible SqlDateTime is 1/1/1753!!! The exception it throws
looks like this:
NHibernate.Event.Default.AbstractFlushingEventListener - Could not synchronize database state with session NHibernate.HibernateException:at System.Data.SqlTypes.SqlDateTime.FromTimeSpan(TimeSpan value) at System.Data.SqlTypes.SqlDateTime.FromDateTime(DateTime value) at System.Data.SqlClient.MetaType.FromDateTime(DateTime dateTime, Byte cb) at at at at at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery() at NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery() --- End of inner exception stack trace --- at NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery() at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps) at NHibernate.AdoNet.AbstractBatcher.ExecuteBatch() at NHibernate.Engine.ActionQueue.ExecuteActions(IList list) at NHibernate.Engine.ActionQueue.ExecuteActions() at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) at NHibernate.Impl.SessionImpl.Flush() at NHibernate.Transaction.AdoTransaction.Commit() |
The easiest fix is to make the class
property use Nullable<T> type, in this case "DateTime?".
Alternatively, you could implement a custom type mapper by implementing
IUserType with its Equals method properly comparing DbNull.Value with
whatever default value of your value type. In our case Equals would need
to return true when comparing 1/1/0001 with DbNull.Value. Implementing a
full-functional IUserType is not really that hard but it does require
knowledge of NHibernate trivia so prepare to do some substantial
googling if you choose to go that way.
Hope this helps somebody!
Why NHibernate updates DB on commit of read-only transaction的更多相关文章
- ABAP-关于隐式与显式的DB Commit
转载:https://www.cnblogs.com/liaojunbo/archive/2011/07/11/2103491.html 1.显式的DB Commit 显式的DB Commit并没有对 ...
- The Architecture of Open Source Applications: Berkeley DB
最近研究内存关系数据库的设计与实现,下面一篇为berkeley db原始两位作为的Berkeley DB设计回忆录: Conway's Law states that a design reflect ...
- spring.net 集成nhibernate配置文件(这里暴露了GetCurrentSession 对于 CurrentSession unbond thread这里给出了解决方法)
我这里主要分成了两个xml来进行spring.net管理实际情况中可自己根据需要进行分类 Dao2.xml <?xml version="1.0" encoding=&quo ...
- NHibernate系列文章十四:NHibernate事务
摘要 NHibernate实现事务机制非常简单,调用ISession.BeginTransaction()开启一个事务对象ITransaction,使用ITransaction.Commit()提交事 ...
- NHibernate系列文章十六:使用程序集管理NHibernate项目(附程序下载)
摘要 在实际的项目中,经常是将NHibernate的实体关系映射类做成独立的工程(assembly dll),只对外提供Session调用的接口.这个程序集作为数据访问层,可以被上面的多个工程(ASP ...
- NHibernate Session-per-request and MiniProfiler.NHibernate
NHibernate Session-per-request and MiniProfiler.NHibernate 前言 1.本文以mvc3为例,借鉴开源项目 NerdDnner项目完成nhiber ...
- Python DB operation
mysql http://www.cnblogs.com/zhangzhu/archive/2013/07/04/3172486.html 1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目 ...
- sqlachemy 获取新创建对象的id,flush与commit
for account_info in valid_account_detail: try: account = account_info.get('account') password = acco ...
- 关于NHibernate的一些代码
SessionManager using System; using System.IO; using System.Runtime.Serialization; using System.Runti ...
随机推荐
- Controller之间传递数据:属性传值
在项目中,Controller之间传递数据非常之多,这里简单介绍一下属性传值.例如有FirstController 和 SecondController,数据从First传递到Second中,我们如何 ...
- linux使用技巧
<1>vim /etc/hosts.deny sshd : 192.168.0.25 :deny //ssh拒绝某ip或网段访问.(原理详见鸟哥基础版18章P56 ...
- 【OpenStack】OpenStack系列15之OpenStack高可用详解
高可用 概念 级别 陈本 如何实现 分类 Openstack的HA 虚拟机的HA 虚拟机HA 比较 应用级别HA,Heat的HA模板 组件的HA 示意图 Mysql的HA 三种方式之一——主从同步 ...
- 如何利用phpize在生产环境中为php添加新的扩展php-bcmath
在日常的开发当中,随着开发的功能越来越复杂.对运行环境的要求也就随着需求的变化需要不断地更新和变化.一个在线的生产系统不可能一开始就满足了所有的运行依赖,因此动态地添加依赖就显得比较必要了.如果你的应 ...
- Android Intent不可传递大数据
今天用intent传递一个bitmap,结果一直出错,intent无法执行,原来是intent不能传递大数据导致的,具体是多大,不太清楚,但我传递的bitmap在1m以上.
- 15.python笔记之psutil模块
一.psutil模块 1. psutil是一个跨平台库(http://code.google.com/p/psutil/),能够轻松实现获取系统运行的进程和系统利用率(包括CPU.内存.磁盘.网络等) ...
- MFC 相关文件夹、文件操作
//关于文件(夹)操作,可以参考下SHFileOperation这个外壳函数,貌似可以显示进度条.以下没有使用SHFileOperation//删除一个文件夹下的所有内容void myDeleteDi ...
- Emblog 备忘
emblog换后台:(如admin-->xx) 1.xx目录下的globals.php打开找到替换admin(1) 2.www目录下的t\index.php 中找到替换admin(1) 3.ww ...
- Hibernate日常应用的相关问题
1.在控制台中显示Hibernate打印的SQL中的参数 默认情况下,hibernate的sql中都是以问号代表参数,并没有显示参数的真实值,但是也不是做不到,只需要两步配置就可以显示出参数的真实值了 ...
- Java Hour 59 JVM Heap
程序没有方法区释放一段Heap 上的内存,只有JVM 本身可以去回收内存,这个工作单位就是GC. Garbage Collection GC 用来清理对象,同时也用来移动对象减少内存碎片. JVM 指 ...