SQL ExecuteNonQuery时出现异常:是否可以避免回滚?

时间:2016-01-18 14:01:36

标签: c# sql-server varbinary

将流写入var-binary字段,如下所示:

ID_Entry = 1

当异常发生时,所有到目前为止写入的数据都消失了。因此,在发生异常的情况下似乎存在某种回滚。有没有办法存储迄今为止的书面数据?它将在稍后恢复,所以我现在不在乎它是否完整。

快速示例: 我正在使用的流是网络流。在将数据写入数据库时​​获取数据。 假设流的大小为1000字节。如果已经接收到900个字节(并以某种方式在数据库中的某处自动缓冲),然后发生连接问题(IOException),则所有数据都将丢失。什么都不会存储到数据库中。但我希望将这900个字节存储到var-binary字段中(稍后将恢复其余部分)。

1 个答案:

答案 0 :(得分:1)

一些事情:

  • 我非常确定SqlServer不支持"部分列更新"的概念。更新将完全发生,或者不会发生。

  • 您可以将尽可能多的流复制到字节数组或MemoryStream中,而不是直接将流作为参数传递,然后传递它。这将使您可以控制错误处理。这无法工作的唯一原因是:(1).NET sql客户端能够将字节流式传输到数据库而不将它们全部收集到内存中,并且(2)您依赖于此优化。

  • 另一个潜在的解决方法是分批进行写作。不要尝试一次写入整个流,而是创建一个循环,在其中读取流的下N个字节,并发出尝试将这些字节附加到现有列的查询。这将导致更多往返数据库,但应该为您提供所需的部分更新。

  • 我假设"错误"有问题的是在对Stream.Read()的调用中发生,它会中断将数据从流中拉入SQL的过程。如果这是真的,那么另一个可能的解决方案可能是将您的流包装在另一个Stream实现中,该实现捕获相关错误并在那里结束流。类似的东西:


class ErrorSuppressingStream : Stream
{
    private readonly Stream inner;

    public bool TerminatedWithError { get; private set; }

    public ErrorSuppressingStream(Stream inner) { this.inner = inner; }

    public override int Read(byte[] buffer, int offset, int count)
    {
        if (this.TerminatedWithError) { return 0; }

        try { return this.inner.Read(buffer, offset, count); }
        catch (XXXException ex)
        {
            this.TerminatedWithError = true;
            return 0;
        }
    }

    // more overrides here
}

这将允许您仍然将字节流式传输到数据库,但会将读取错误视为流的结尾而不是抛出。