Write SqlDataReader to immediate window c#

旧时模样 提交于 2019-12-01 21:05:42

How do I write SqlDataReader when debugging on the fly to immediate window?

SqlDataReader implements the interface IDataReader. The following tricks apply to any reader implementing this interface. As with (new System.IO.StreamReader(stream)).ReadToEnd(), these techniques will consume the contents of the data reader, so it will no longer be usable.

Dumping results purely on the fly.

If you don't have time to prepare and need to look at your reader's contents right away, you can load your data reader into a DataTable defined in the immediate window, them print out the XML for that table.

First, define three run-time global variables in the immediate window by typing:

object [] _objs = null;
DataTable _table = null;
DataSet _set = null;

Do this once per session.

Next, if the code has already begun to read through the table columns, you can get the values of the current row by typing:

_objs = new object[dataStream.FieldCount];
dataStream.GetValues(_objs);
_objs

The current values will now be displayed.

Then, to read in and display the remainder of the rows, do the following:

_table = new DataTable();
_table.Load(dataStream);
_set = new DataSet();
_set.Tables.Add(_table);
_set.GetXml();
Debug.WriteLine(_set.GetXml());

You will see the contents of _set printed out in the Immediate Window as an XML string. Note that if the table is partially read, DataTable.Load(IDataReader) will skip the current row, so dump the current values first.

This works well for readers corresponding to a single table, but not for readers corresponding to multiple tables that form a set.

Dumping results using a small debugging library.

If you have a little time to prepare or need to debug a multi-table reader, you can do the following.

First, create a small debugging DLL project with utilities such as the following. You do not need to link this into the project you are actually debugging.

namespace DataReaderDebugUtilities
{
    public static class DataReaderExtensions
    {
        public static object[] CurrentValues(this IDataReader reader)
        {
            if (reader == null)
                throw new ArgumentNullException();
            var objs = new object[reader.FieldCount];
            reader.GetValues(objs);
            return objs;
        }

        public static KeyValuePair<string, object> [] CurrentNamesAndValues(this IDataReader reader)
        {
            if (reader == null)
                throw new ArgumentNullException();
            var query = Enumerable.Range(0, reader.FieldCount).Select(i => new KeyValuePair<string, object>(reader.GetName(i), reader.GetValue(i)));
            return query.ToArray();
        }

        public static string ToStringAsDataTable(this IDataReader reader)
        {
            if (reader == null)
                throw new ArgumentNullException();
            var sb = new StringBuilder();
            using (var textWriter = new StringWriter(sb))
            using (var jsonWriter = new JsonTextWriter(textWriter) { Formatting = Formatting.Indented })
            {
                var serializer = JsonSerializer.CreateDefault();
                jsonWriter.WriteDataTable(reader, serializer);
            }
            return sb.ToString();
        }

        public static string ToStringAsDataSet(this IDataReader reader)
        {
            if (reader == null)
                throw new ArgumentNullException();
            var sb = new StringBuilder();
            using (var textWriter = new StringWriter(sb))
            using (var jsonWriter = new JsonTextWriter(textWriter) { Formatting = Formatting.Indented })
            {
                var serializer = JsonSerializer.CreateDefault();
                jsonWriter.WriteDataSet(reader, serializer);
            }
            return sb.ToString();
        }
    }

    public static class JsonExtensions
    {
        public static void WriteDataTable(this JsonWriter writer, IDataReader reader, JsonSerializer serializer)
        {
            if (writer == null || reader == null || serializer == null)
                throw new ArgumentNullException();
            writer.WriteStartArray();
            while (reader.Read())
            {
                writer.WriteStartObject();
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    writer.WritePropertyName(reader.GetName(i));
                    serializer.Serialize(writer, reader[i]);
                }
                writer.WriteEndObject();
            }
            writer.WriteEndArray();
        }

        public static void WriteDataSet(this JsonWriter writer, IDataReader reader, JsonSerializer serializer)
        {
            if (writer == null || reader == null || serializer == null)
                throw new ArgumentNullException();
            writer.WriteStartObject();

            do
            {
                var tableName = string.Empty;
                var schemaTable = reader.GetSchemaTable();
                if (schemaTable != null)
                    tableName = schemaTable.Rows.Cast<DataRow>()
                        .Select(r => r[schemaTable.Columns[System.Data.Common.SchemaTableColumn.BaseTableName]].ToString())
                        .FirstOrDefault();
                writer.WritePropertyName(tableName ?? string.Empty);
                writer.WriteDataTable(reader, serializer);
            }
            while (reader.NextResult());

            writer.WriteEndObject();
        }
    }
}

(Note - the code to get the table name is not fully tested.)

Note I am using to serialize result values and format the overall results. You could use a different serializer if you prefer.

Build the project in debug mode and copy it to a convenient location, say C:\Temp\DataReaderDebugUtilities.dll.

Next, when you need to dump the values inside a data reader, in the immediate window, type:

Assembly.LoadFile(@"C:\Temp\DataReaderDebugUtilities.dll");

Now you can call methods from this DLL in the immediate window even though it is not linked into your project. Thus typing:

DataReaderDebugUtilities.DataReaderExtensions.CurrentNamesAndValues(dataStream)

will show you the names and values of the current row, if any.

Then typing

string _s = DataReaderDebugUtilities.DataReaderExtensions.ToStringAsDataSet(dataStream);

or

string _s = DataReaderDebugUtilities.DataReaderExtensions.ToStringAsDataTable(dataStream);

will dump the remaining contents of the reader as a data table or data set into a JSON string for manual inspection.

  • You could set a breakpoint inside Dapper code - is Open Source.
  • Result1 is defined as varchar(50), but your C# class says decimal.

Conversion failed when converting the varchar value '0.01' to data type bit.
i think the message is thrown by SQL server. so there should be error at SQL level. Try checking actual query in SQL profiler and run in SSMS.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!