Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.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
C# SqlDataReader.Read和大型记录_C#_Sql Server 2012_Sqldatareader - Fatal编程技术网

C# SqlDataReader.Read和大型记录

C# SqlDataReader.Read和大型记录,c#,sql-server-2012,sqldatareader,C#,Sql Server 2012,Sqldatareader,当使用SqlDataReader时,我会有一些奇怪的行为。当结果集包含一个大列时读取 发生的情况是: 不读取整个记录 读卡器和连接关闭后,记录保持锁定状态。 除非我在大列上显式调用reader.Get* 这里有一些测试代码来说明我的意思 CREATE TABLE TestXml ( Id int NOT NULL ,number int NOT NULL ,data xml NOT NULL ); INSERT INTO TestXml VALUES (1, 0, (SEL

当使用SqlDataReader时,我会有一些奇怪的行为。当结果集包含一个大列时读取

发生的情况是:

不读取整个记录 读卡器和连接关闭后,记录保持锁定状态。 除非我在大列上显式调用reader.Get*

这里有一些测试代码来说明我的意思

CREATE TABLE TestXml (
    Id int NOT NULL
   ,number int NOT NULL
   ,data xml NOT NULL
);

INSERT INTO TestXml
VALUES (1, 0, (SELECT TOP 100 * FROM sys.objects FOR XML PATH('Objects')))
      ,(2, 0, (SELECT TOP 1000 * FROM sys.objects FOR XML PATH('Objects')))
      ,(3, 0, (SELECT TOP 10000 a.* FROM sys.objects a, sys.objects b FOR XML PATH('Objects')))
获取数据的代码

const int TestId = 1;

using (var connection1 = new SqlConnection(ConnectionString))
using (var connection2 = new SqlConnection(ConnectionString))
using (var command1 = new SqlCommand())
using (var command2 = new SqlCommand()) {
    command1.Connection = connection1;
    command1.CommandText =
        "SELECT Id, number, data " +
        "FROM TestXml " +
        "WHERE Id = @Id";

    command2.Connection = connection2;
    command2.CommandText = 
        "UPDATE TestXml " + 
        "SET number = number + 1 " +
        "WHERE Id = @Id";

    connection1.Open();
    connection2.Open();

    command1.Parameters.Add("@Id", SqlDbType.Int).Value = TestId;
    using (var reader = command1.ExecuteReader()) {
        if (reader.Read()) {
            var id = reader.GetInt32(0);

            //// reader.GetValue(2);
            command2.Parameters.Add("@Id", SqlDbType.Int).Value = id;
            command2.ExecuteNonQuery();
        }
    }
}
当Id=1或2=>时,更新工作正常。 当Id=3=>超时异常时

如果我取消对reader.GetValue2的注释,Id=3也可以正常工作

这是读者的预期行为吗? 关闭读卡器不应该取消查询并释放锁吗

我知道我可以使用CommandBehavior.SequentialAccess对结果进行流式处理,但在这种情况下,没有计划使用大型对象

编辑:只是为了表明在读卡器关闭后不需要更新就可以保留锁。任何异常都会关闭读卡器,但会保持对记录的锁定,例如

using (var connection1 = new SqlConnection(ConnectionString))
using (var command1 = new SqlCommand())
    command1.Connection = connection1;
    command1.CommandText =
        "SELECT Id, number, data " +
        "FROM TestXml " +
        "WHERE Id = 3";

    connection1.Open();

    using (var reader = command1.ExecuteReader()) {
        if (reader.Read()) {
            var id = reader.GetInt32(0);
            throw new Exception("whatever");
        }
    }
}

第3行仍然被锁定

两个建议1将命令超时设置为更大的数字。默认值为5分钟,可能不够长,无法完成查询。2将查询放入BackGroundWorker,这样应用程序就不会被锁定。当我在表单应用程序中有一个大型SQL查询时,表单会挂起,因此将查询放入BackGroundWorker可以使表单在查询运行时仍能运行。我认为,在不同连接中访问同一个表的方式可能会遇到锁定问题等;这就是你其他问题的原因。很难说,因为这种方法似乎很奇怪;从一个表中运行select以在另一个表中再次更新它,而这可以在一个查询中完成—但幕后可能有比这更多的内容?@jdweng。这只是一个示例,说明reader.Read可能不会读取整个记录,并且在关闭reader时锁可能不会被清除。我的代码非常不同,但有相同的问题。对于非常大的数据库,我一直使用sqlcmd.exe并将结果保存到csv文件中。我有使用backgroundworker从c运行sqlcmd.exe的代码。然后我将csv读入c来完成处理。@jdweng,我的数据库相当小。意外地,一个大的xml被插入到一个表中,这导致了各种各样的麻烦。我四处查看了一下,但没有发现任何关于在可能包含较大值的表上使用SqlDataReader的警告。当结果集中有varcharmax、varbinarymax或xml列时,每个人都会立即切换到SequentialAccess吗?否则,这似乎是一个可能的DOS攻击的机会。有两个建议1将命令超时设置为一个更大的数字。默认值为5分钟,可能不够长,无法完成查询。2将查询放入BackGroundWorker,这样应用程序就不会被锁定。当我在表单应用程序中有一个大型SQL查询时,表单会挂起,因此将查询放入BackGroundWorker可以使表单在查询运行时仍能运行。我认为,在不同连接中访问同一个表的方式可能会遇到锁定问题等;这就是你其他问题的原因。很难说,因为这种方法似乎很奇怪;从一个表中运行select以在另一个表中再次更新它,而这可以在一个查询中完成—但幕后可能有比这更多的内容?@jdweng。这只是一个示例,说明reader.Read可能不会读取整个记录,并且在关闭reader时锁可能不会被清除。我的代码非常不同,但有相同的问题。对于非常大的数据库,我一直使用sqlcmd.exe并将结果保存到csv文件中。我有使用backgroundworker从c运行sqlcmd.exe的代码。然后我将csv读入c来完成处理。@jdweng,我的数据库相当小。意外地,一个大的xml被插入到一个表中,这导致了各种各样的麻烦。我四处查看了一下,但没有发现任何关于在可能包含较大值的表上使用SqlDataReader的警告。当结果集中有varcharmax、varbinarymax或xml列时,每个人都会立即切换到SequentialAccess吗?否则,这似乎是一个可能的拒绝服务攻击的机会。