我有一个应用程序可能会对SQL Server 2005数据库进行数千次插入.如果插入因任何原因(外键约束,字段长度等)而失败,则应用程序将记录插入错误并继续.
每个插入都独立于其他插入,因此数据库完整性不需要事务.但是,我们希望使用它们来提高性能.当我使用事务时,我们将在每100次提交中大约有1次出现以下错误.
This SqlTransaction has completed; it is no longer usable. at System.Data.SqlClient.SqlTransaction.ZombieCheck() at System.Data.SqlClient.SqlTransaction.Commit()
为了尝试追踪原因,我在每个事务操作中都放置了trace语句,这样我就可以确保在调用commit之前没有关闭事务.我已经确认我的应用程序不会关闭交易.然后我使用完全相同的输入数据再次运行应用程序并成功.
如果我关闭日志,它会再次失败.把它重新打开,然后成功.这个开/关切换是通过app.config完成的,无需重新编译.
显然,记录行为会改变时间并使其起作用.这表明存在线程问题.但是,我的应用程序不是多线程的.
我已经看到一个MS KB条目表明.Net 2.0框架的错误可能会导致类似的问题(http://support.microsoft.com/kb/912732).但是,他们提供的修复程序无法解决此问题.
感谢所有的反馈.我一直在MSDN论坛上与MSFT的某个人合作,以弄清楚发生了什么.事实证明,问题是由于日期时间转换问题导致其中一个插入失败.
主要问题是,如果是日期转换错误,则会显示此错误.但是,如果它是另一个错误,例如字段太长,则不会导致此问题.在这两种情况下,我都希望事务仍然存在,所以我可以在其上调用Rollback.
我有一个完整的示例程序来复制此问题.如果有人希望看到它或与MSFT交换,您可以在SqlTransaction.ZombieCheck错误线程下的microsoft.public.dotnet.framework.adonet中的MSFT新闻组中找到该线程.
没有看到代码就很难提供帮助.我假设您在描述中使用事务在每N个插入后提交,这将提高性能与提交每个插入,前提是N不是太大.
但缺点是:如果插入失败,当您回滚事务时,当前批次N中的任何其他插入将被回滚.
通常,您应该在关闭连接之前处置事务(如果事务尚未提交,则会回滚事务).通常的模式类似于以下内容:
using(SqlConnection connection = ...) { connection.Open(); using(SqlTransaction transaction = connection.BeginTransaction()) { ... do stuff ... transaction.Commit(); // commit if all is successful } // transaction.Dispose will be called here and will rollback if not committed } // connection.Dispose called here
如果您需要更多帮助,请发布代码.
请记住,您的应用程序不是事务的唯一参与者 - 也涉及SQL Server.
你引用的错误:
这个SqlTransaction已经完成; 它不再可用.System.Data.SqlClient.SqlTransaction.Commit()中的System.Data.SqlClient.SqlTransaction.ZombieCheck()
并不表示交易已经完成,只是表示已完成.
我的第一个建议是你的服务器已经终止了交易,因为它要么花费太长时间(耗尽时间)或者太大(更改太多或锁太多).
我的第二个建议是检查您是否正确清理了连接和交易.您可能会遇到问题,因为在事情自动回收之前,您偶尔会耗尽一些资源.
例如,DbConnection
实现IDisposable,因此您需要确保适当地清理 - 如果可以,使用using语句,或者如果不能,则通过Dispose()
直接调用.'DbCommand'类似,因为它也实现了IDisposable
.