Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net SqlTransaction已完成_.net_Sql Server_Sql Server 2005_Transactions - Fatal编程技术网

.net SqlTransaction已完成

.net SqlTransaction已完成,.net,sql-server,sql-server-2005,transactions,.net,Sql Server,Sql Server 2005,Transactions,我有一个应用程序,它可以向SQLServer2005数据库进行数千次插入。如果插入因任何原因(外键约束、字段长度等)失败,应用程序将记录插入错误并继续 每个插入都独立于其他插入,所以数据库完整性不需要事务。但是,我们确实希望使用它们来提高性能。当我使用事务时,每100次提交中大约有1次会出现以下错误 This SqlTransaction has completed; it is no longer usable. at System.Data.SqlClient.SqlTransacti

我有一个应用程序,它可以向SQLServer2005数据库进行数千次插入。如果插入因任何原因(外键约束、字段长度等)失败,应用程序将记录插入错误并继续

每个插入都独立于其他插入,所以数据库完整性不需要事务。但是,我们确实希望使用它们来提高性能。当我使用事务时,每100次提交中大约有1次会出现以下错误

This SqlTransaction has completed; it is no longer usable.
   at System.Data.SqlClient.SqlTransaction.ZombieCheck()
   at System.Data.SqlClient.SqlTransaction.Commit()
为了找出原因,我在每个事务操作中都放上跟踪语句,以便在调用commit之前确保事务没有关闭。我已确认我的应用程序无法关闭交易。 然后,我使用完全相同的输入数据再次运行应用程序,结果成功了

如果我关闭日志记录,它会再次失败。打开它,它就会成功。此开/关切换通过app.config完成,无需重新编译

显然,日志记录的行为改变了时间并使其工作。这表明存在线程问题。然而,我的应用程序不是多线程的


我看到一个MS KB条目表明.Net 2.0 framework的bug可能会导致类似的问题()。但是,他们提供的修复无法解决此问题。

如果不查看代码,很难提供帮助。根据您的描述,我假设您在每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也参与其中

您引用的错误:

此事务已完成;信息技术 不再可用。在 System.Data.SqlClient.SqlTransaction.ZombieCheck() 在 System.Data.SqlClient.SqlTransaction.Commit()

不表示事务已提交,只表示事务已完成

我的第一个建议是,您的服务器已经终止了事务,因为它花费了太长的时间(ellapsed wall time)或者太大(太多更改或太多锁)

我的第二个建议是检查您是否适当地清理了连接和事务。你可能会遇到问题,因为在东西被自动回收之前,你偶尔会耗尽一些资源


例如,实现,因此您需要确保适当地清理—如果可以,可以使用语句,或者如果不能,则直接调用
Dispose()
。与此类似,因为它还实现了IDisposable

首先,在我看来,你不应该期望你的应用程序能够处理这样的“硬”错误。您的应用程序应该了解这些业务规则是什么,并对其进行说明。不要强迫数据库成为业务规则或约束规则。它应该只是一个数据规则cop,并且在这一点上,要优雅地用返回和其他方法告诉接口。模式的东西不应该被强迫这么做

在回答您的问题时,在没有看到任何代码的情况下,我怀疑您正在尝试在发生错误时进行提交,而您还不知道。这就是我第一次陈述的理由。。。在应用程序不理解和参与这些规则的情况下,试图捕捉数据库所给出的错误,这让您感到头疼

试试这个。插入不会因数据库约束或其他错误而失败的行,并通过提交处理插入。看看会发生什么。然后插入一些将失败的记录,处理一个提交,看看你是否得到了你可爱的错误。第三,再次运行错误,执行强制回滚,然后查看是否成功

只是一些想法。同样,作为一个总结,我认为这与不以优雅的方式从数据库中捕获某些“硬”错误有关,并期望前端处理它们。再一次,我的专家意见是,不,不要这样做。一团糟。你的应用程序需要在背面规则的知识上重叠。这些东西的存在只是为了确保在测试期间不会发生这种情况,以及偶尔出现这样的错误,然后将其放在前面,以处理对外键表集的遗忘查找


希望能有所帮助。

您已经证明您的数据没有任何合理的疑问。
不管好坏 我更愿意将insert移动到存储过程中,并且根本不使用事务。
如果您需要UI响应,请使用后台工作人员执行数据库咕哝。
对我来说,事务是用于相互关联的活动,而不是节省时间的设备。 插入成本必须在线路的某个地方支付

我最近在一个数据库应用程序上使用了ANTS profiler,并惊奇地看到在稳定运行的代码中显示间歇的SQlClient异常。打开连接时,框架中的错误很深。它们永远不会浮出水面,客户端代码也无法检测到它们。 所以 要点是什么?
外面的一切都不是坚如磐石,把繁重的工作从U.I.移开,接受成本。 嗯
鲍勃

谢谢你的反馈。我一直在和MSFT的人在MSDN论坛上合作,想弄清楚到底发生了什么。事实证明,问题是由于其中一个插入由于日期-时间转换问题而失败

主要问题是,如果是日期转换错误,则会显示此错误。但是,如果是另一个错误,例如字段太长,则不会导致此问题。在这两种情况下,我都希望交易
    public static void TryRollback(this System.Data.IDbTransaction t)
    {
        try
        {
            t.Rollback();
        }
        catch (Exception ex)
        {
            // log error in my case
        }
    }

    public static void TryCommit(this System.Data.IDbTransaction t)
    {
        try
        {
            t.Commit();
        }
        catch (Exception ex)
        {
            // log error in my case
        }
    }
This SqlTransaction has completed; it is no longer usable
CREATE PROCEDURE sp_ShrinkLog_ByDataBaseName(
@DataBaseName VARCHAR(200)
)
AS
BEGIN

DECLARE @DBName VARCHAR(200)
DECLARE @LogFileName VARCHAR(200)
SET @DBName = @DataBaseName

SELECT @LogFileName = [Logical File Name]
FROM
(
SELECT
    DB_NAME(database_id)  AS "Database Name", 
type_desc             AS "File Type", 
name                  AS "Logical File Name", 
physical_name         AS "Physical File", 
state_desc            AS "State"
FROM
    SYS.MASTER_FILES
WHERE
    database_id = DB_ID(@DBName)
    and type_desc = 'LOG'
) AS SystemInfo
SELECT LogFileName = @LogFileName

EXECUTE(
'USE ' + @DBName + ';

-- Truncate the log by changing the database recovery model to SIMPLE.
ALTER DATABASE ' + @DBName + '
SET RECOVERY SIMPLE;

-- Shrink the truncated log file to 1 MB.
DBCC SHRINKFILE (' + @LogFileName + ', 1);

-- Reset the database recovery model.
ALTER DATABASE ' + @DBName + '
SET RECOVERY FULL;

')
END