mar*_*ark 2 database nhibernate
我们已经从sqlite切换到FireBird嵌入式服务器,因为FB似乎支持数据库的并发更新,但我们有时会遇到这些异常:
2010-10-28 15:49:31,242 [56] ERROR NetworkCatcher.Entities.Agent.Server.RunResultManager - Failed to send result to server 32W2K3SP2VM-DEV. NHibernate.Exceptions.GenericADOException: could not update: ExecutionEntry#89_19_32W2K3SP2VM-DEV][SQL: UPDATE Run SET ExecutionId = ?, Source = ?, Destination = ?, ProtocolId = ?, Duration = ?, SampleCount = ?, StartTime = ?, ServerHostName = ?, SamplesSentToServer = ?, SampleInterval = ?, Parameters = ? WHERE Id = ?] ---> FirebirdSql.Data.FirebirdClient.FbException: deadlock
update conflicts with concurrent update
concurrent transaction number is 31632 --->
FirebirdSql.Data.Common.IscException: deadlock
update conflicts with concurrent update
concurrent transaction number is 31632
at FirebirdSql.Data.Client.Native.FesDatabase.ParseStatusVector(IntPtr[]
statusVector)
at FirebirdSql.Data.Client.Native.FesStatement.Execute()
at FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteCommand(CommandBehavior
behavior, Boolean returnsSet)
at FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteCommand(CommandBehavior
behavior)
at FirebirdSql.Data.FirebirdClient.FbCommand.ExecuteNonQuery()
.
.
.
Run Code Online (Sandbox Code Playgroud)
FB对此的反应是"为什么你认为这是一个错误?这是由两个事务同时更新同一记录导致的定期更新冲突.你的交易隔离模式是什么?"
这句话让我困惑了两次 - 一次,因为我发现我可能会同时写同一条记录并且第二次 - 我不知道什么是我的事务隔离模式以及如何使用它来序列化写入同样的记录.
正在更新的对象的映射是:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-
import="true">
<class name="NetworkCatcher.Entities.Agent.Server.ExecutionManager+ExecutionEntry,NC.Entities.Agent.Server" lazy="false" table="Run" entity-name="ExecutionEntry">
<id name="Id" column="Id" type="string" >
<generator class="assigned"/>
</id>
<property name="ExecutionId"/>
<property name="Source"/>
<property name="Destination"/>
<property name="ProtocolId" type="string"/>
<property name="Duration"/>
<property name="SampleCount"/>
<property name="StartTime"/>
<property name="ServerHostName"/>
<property name="m_samplesSentToServer" column="SamplesSentToServer" type="int" access="field" />
<property name="SampleInterval"/>
<property name="Parameters" type="binary"/>
</class>
</hibernate-mapping>
Run Code Online (Sandbox Code Playgroud)
我相信那里有一个好的撒玛利亚人,谁知道我的问题的答案.拜托,请分享你的智慧......
谢谢.
事务隔离模式通常在hibernatem.cfg.xml文件中设置:
<property name ="connection.isolation"> ReadCommitted </ property>
http://www.nhforge.org/doc/nh/en/index.html#configuration-hibernatejdbc
您可以在System.Data.IsolationLevel的MSDN文档中找到有效值的列表和每个值的说明:
http://msdn.microsoft.com/en-us/library/system.data.isolationlevel.aspx
您必须检查FireBird文档以查看它支持的文档.
对于您的异常,您在更新记录时遇到了死锁,这在关系数据库中是预期的.您应该准备好捕获死锁异常并重新尝试操作.这与NHibernate没有任何关系,也与关系数据库如何支持事务有关.基本上你遇到了一种情况,你试图在两个不同的交易中更新相同的两个记录A和B. 一个事务对A有锁定,另一个事务对B有锁定.每个事务需要锁定另一个记录才能完成.数据库引擎选择死锁牺牲品,回滚其事务,将其抛出死锁异常,并允许其他事务完成.如果没有这样做,两个事务都将等待另一个事务完成(或事务超时).(这可能是一个更复杂的记录循环,r1..rN和多个事务,但同样的想法适用.)最终结果是,作为应用程序开发人员,您必须准备重新尝试死锁操作,您是使用NHibernate,原始ADO.NET还是使用关系数据库的任何其他技术.