SqlDataReader跳过某些结果集中的结果

本文关键字:结果 集中 SqlDataReader | 更新日期: 2023-09-27 18:29:38

我正在将数据读取器的结果序列化为WEB API应用程序中的JSON。我没有使用预定义的类来保存来自读取器的数据。正在将生成的JSON与来自sql server management studio的结果进行比较。在这两种情况下,都在执行具有相同参数的相同存储过程。共有8个结果集。应该有20行的第5个结果集返回0个结果。第7个结果集包含2行而不是8行。

在这两种情况下,我都使用SO上的代码,我对其进行了一些更改:第一种情况-手动创建序列化对象:

public JsonResult<Dictionary<string, List<Dictionary<string, object>>>> Get()
    {
        Dictionary<string, List<Dictionary<string, object>>> r = null;
        using (var conn = new SqlConnection(_connString))
        {
            using (var command = new SqlCommand("getReportData", conn) { CommandType = CommandType.StoredProcedure })
            {
                command.Parameters.AddWithValue("@DateFrom", new DateTime(2014, 6, 1, 0, 0, 0));
                command.Parameters.AddWithValue("@DateTo", new DateTime(2014, 6, 1, 0, 0, 0));
                command.Parameters.AddWithValue("@UserIDList", "1,2,3,4,5,6,7");
                conn.Open();
                command.ExecuteNonQuery();
                reader = command.ExecuteReader();
                r = Serialize(reader);
            }
        }
        return Json(r, new JsonSerializerSettings {Formatting = Formatting.Indented});
    }
public Dictionary<string, List<Dictionary<string, object>>> Serialize(SqlDataReader reader)
    {
        string resultSetName = "resultSet_";
        int resultSetCount = 1;
        var sets = new Dictionary<string, List<Dictionary<string, object>>>();
        var results = new List<Dictionary<string, object>>();
        var cols = new List<string>();
        for (var i = 0; i < reader.FieldCount; i++)
            cols.Add(reader.GetName(i));
        while (reader.Read())
            results.Add(SerializeRow(cols, reader));
        sets.Add(resultSetName + resultSetCount, results);
        while (reader.NextResult())
        {
            resultSetCount++;
            var resultsTmp = new List<Dictionary<string, object>>();
            var colsTmp = new List<string>();
            for (var i = 0; i < reader.FieldCount; i++)
            {
                colsTmp.Add(reader.GetName(i));
            }
            while (reader.Read())
            {
                resultsTmp.Add(SerializeRow(colsTmp, reader));
            }
            var setTmp = new Dictionary<string, List<Dictionary<string, object>>>();
            sets.Add(resultSetName + resultSetCount, resultsTmp);
        }
        return sets;
    }
    private Dictionary<string, object> SerializeRow(IEnumerable<string> cols,
                                                    SqlDataReader reader)
    {
        var result = new Dictionary<string, object>();
        foreach (var col in cols)
            result.Add(col, reader[col]);
        _loopRowCount++;
        return result;
    }

第二种情况-使用数据适配器,编写字典并将结果序列化为json:

public JsonResult<Dictionary<string, DataTable>> Get()
    {
        string setName = "resultSet_";
        int setCount = 1;
        var dataTables = new Dictionary<string, DataTable>();
        using (var connection = new SqlConnection(_connString))
        {
            using (var command = new SqlCommand("getReportData", connection) { CommandType = CommandType.StoredProcedure })
            {
                command.Parameters.AddWithValue("@DateFrom", new DateTime(2014, 6, 1, 0, 0, 0));
                command.Parameters.AddWithValue("@DateTo", new DateTime(2014, 6, 1, 0, 0, 0));
                command.Parameters.AddWithValue("@UserIDList", "1,2,3,4,5,6,7");
                connection.Open();
                var adapter = new SqlDataAdapter(command);
                var set = new DataSet();
                adapter.SelectCommand = command;
                adapter.Fill(set);
                foreach (DataTable t in set.Tables)
                {
                    dataTables.Add(setName + setCount, t);
                    setCount++;
                }
            }
        }
        return Json(dataTables, new JsonSerializerSettings { Formatting = Formatting.Indented });
    }

以下是在SSMS 中执行存储过程的代码

USE [DB]
GO
DECLARE @return_value int
EXEC    @return_value = [dbo].[getReportData]
        @DateFrom = '2013-06-01 00:00:00',
        @DateTo = '2013-06-30 00:00:00',
        @UserIDList = '1,2,3,4,5,6,7'
SELECT  'Return Value' = @return_value
GO

两种方法都会丢失完全相同的数据,而执行存储过程显然会返回更多的数据。我重复一遍,在所有三种情况下,都是相同的存储过程,相同的参数。

奇怪的是,生产代码使用这个存储过程,但将数据从读取器映射到预定义的类,并且没有丢失任何数据。

为什么读者会"忽略"程序明显返回的数据,以及如何防止这种情况发生?

SqlDataReader跳过某些结果集中的结果

根据发布的代码,在SSMS和C#中执行@DateFrom@DateTo的值是不同的。