我有多个客户端通过不可靠的(无线/ gprs)网络连接到SQL Server,并在几分钟内执行大量的小型查询和插入操作。 如果在此过程中网络连接断开,则整个事务将回滚并需要重新启动。 由于业务需求,流程必须是事务性的(即,其他客户只能从其他客户那里看到完整的数据集,或者根本看不到它)。

我希望能够检测到何时断开连接,并能够重新连接到SQL Server,并刚刚删除的同一事务中继续进行处理并避免从头开始重新启动。 目前,我在打开连接后立即使用sp_getbindtoken ,将CommandTimeout设置为较小的值(比TCP KeepAlive小得多),如果在ExecuteNonQuery期间超时,则打开与服务器的新连接,并从进程开始用令牌调用sp_bindsession 然后,我使用与会话绑定到上一流程的事务的新连接继续流程。

到目前为止,它几乎可以完美运行,但是据MSDN称 ,该API已被弃用,并将在以后的SQL Server版本中删除。 问题是:如果没有这两个命令,如何获得相同的结果? 还有其他方法可以从断开的TCP连接中恢复事务吗?

编辑/进一步信息:客户端应用程序在带有条形码扫描仪的Windows CE设备上运行。 我同时提供设备和软件,因此我可以随意放置任何需要的东西。 DB由第三方托管在受保护的环境中,我和客户都无法控制它。 我总共要发送约50MB的每日销售数据。 我可以使用SP来保存数据,但是仍然必须传输它,并且使用一个大参数对SP的一次调用在GPRS / EDGE链路上成功的可能性接近0%。

由于整个解决方案都在生产环境中工作,因此我希望将更改降至最低。 具有与sp_bindsession相同语义的替代API将是完美的。

===============>>#1 票数:2

我只是不购买单笔交易需要约50MB的每日销售数据。 我认为,个别销售交易需要用sql-transaction进行包装,但每个交易都更像1K。 您确定不能在存储过程中在服务器上运行几个小事务吗? 如果每个设备都必须是全部或全部,则可以通过小型事务将设备加载到登台表。 设备完成后,在事务中使用服务器上的存储过程刷新登台表。 或仅在完成上传上放一个布尔列,然后在上传完成后在一次更新中翻转该标志。 50MB的事务确实会锤击事务日志并锁定其他更新。

===============>>#2 票数:0

您提供的MSDN链接建议使用MARS 根据这篇文章:

MARS允许将一个连接用于读取操作和数据操作语言(DML)操作,其中有多个挂起操作。 此功能消除了应用程序处理连接繁忙错误的需要。 此外,MARS可以代替服务器端游标的用户,后者通常会消耗更多资源。 最后,由于多个操作可以在单个连接上进行操作,因此它们可以共享同一事务上下文,从而无需使用sp_getbindtoken和sp_bindsession系统存储过程。

这样,您可以使用BeginTrasaction,除非明确提交,否则事务将自动回滚。 您可以捕获commit语句的失败,然后递归地尝试重新提交它,直到事务的提交成功返回为止。 只是一个主意。 也许是这样的:

private static void ExecuteSqlTransaction(string connectionString)
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        SqlCommand command = connection.CreateCommand();
        SqlTransaction transaction;

        // Start a local transaction.
        transaction = connection.BeginTransaction("SampleTransaction");

        // Must assign both transaction object and connection
        // to Command object for a pending local transaction
        command.Connection = connection;
        command.Transaction = transaction;

        try
        {
            command.CommandText =
                "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";
            command.ExecuteNonQuery();
            command.CommandText =
                "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";
            command.ExecuteNonQuery();

            // Attempt to commit the transaction.
            transaction.Commit();
            //Both records are written to database.
        }
        catch (Exception ex)
        {
            // Attempt to roll back the transaction.
            try
            {
                transaction.Rollback();
            }
            catch (Exception ex2)
            {
                // This catch block will handle any errors that may have occurred
                // on the server that would cause the rollback to fail, such as
                // a closed connection.
                ExecuteSqlTransaction(connectionString);
            }
        }
    }
}

  ask by MagnatLU translate from so

未解决问题?本站智能推荐: