SqlDataReader跳过导致一些结果集

时间:2014-11-08 20:46:19

标签: c# sql-server asp.net-web-api

我在WEB API应用程序中将数据读取器的结果序列化为JSON。 我没有使用预定义的类来保存读取器中的数据。 将生成的JSON与sql server management studio的结果进行比较。 在两种情况下都执行具有相同参数的相同存储过程。 有8个结果集。 第5个结果集,应该有20行,返回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

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

有一件奇怪的事情是生产代码使用这个存储过程,但是将数据从阅读器映射到预定义的类,没有数据丢失。

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

1 个答案:

答案 0 :(得分:1)

在发布的代码中,@DateFrom@DateTo的值在SSMS与C#中执行时会有所不同。