How can I easily view the contents of a datatable

2019-01-10 14:13发布

问题:

Sometimes I will be at a breakpoint in my code and I want to view the contents of a datatable variable (or a datatable in a dataset). The quick watch doesn't give you a very clear view of the contents. How can I view them easily?

回答1:

The Visual Studio debugger comes with four standard visualizers. These are the text, HTML, and XML visualizers, all of which work on string objects, and the dataset visualizer, which works for DataSet, DataView, and DataTable objects.

To use it, break into your code, mouse over your DataSet, expand the quick watch, view the Tables, expand that, then view Table[0] (for example). You will see something like {Table1} in the quick watch, but notice that there is also a magnifying glass icon. Click on that icon and your DataTable will open up in a grid view.



回答2:

To beautify adinas's debugger output I made some simple formattings:

    public void DebugTable(DataTable table)
    {
        Debug.WriteLine("--- DebugTable(" + table.TableName + ") ---");
        int zeilen = table.Rows.Count;
        int spalten = table.Columns.Count;

        // Header
        for (int i = 0; i < table.Columns.Count; i++)
        {
            string s = table.Columns[i].ToString();
            Debug.Write(String.Format("{0,-20} | ", s));
        }
        Debug.Write(Environment.NewLine);
        for (int i = 0; i < table.Columns.Count; i++)
        {
            Debug.Write("---------------------|-");
        }
        Debug.Write(Environment.NewLine);

        // Data
        for (int i = 0; i < zeilen; i++)
        {
            DataRow row = table.Rows[i];
            //Debug.WriteLine("{0} {1} ", row[0], row[1]);
            for (int j = 0; j < spalten; j++)
            {
                string s = row[j].ToString();
                if (s.Length > 20) s = s.Substring(0, 17) + "...";
                Debug.Write(String.Format("{0,-20} | ", s));
            }
            Debug.Write(Environment.NewLine);
        }
        for (int i = 0; i < table.Columns.Count; i++)
        {
            Debug.Write("---------------------|-");
        }
        Debug.Write(Environment.NewLine);
    }

Best of this solution: You don't need Visual Studio! Here my example output:

SELECT PackKurz, PackName, PackGewicht FROM verpackungen

PackKurz             | PackName             | PackGewicht          | 
---------------------|----------------------|----------------------|-
BB205                | BigBag 205 kg        | 205                  | 
BB300                | BigBag 300 kg        | 300                  | 
BB365                | BigBag 365 kg        | 365                  | 
CO                   | Container, Alteru... |                      | 
EP                   | Palette              |                      | 
IBC                  | Chemikaliengefäß ... |                      | 
lose                 | nicht verpackungs... | 0                    | 
---------------------|----------------------|----------------------|-


回答3:

What I do is have a static class with the following code in my project:

    #region Dataset -> Immediate Window
public static void printTbl(DataSet myDataset)
{
    printTbl(myDataset.Tables[0]);
}
public static void printTbl(DataTable mytable)
{
    for (int i = 0; i < mytable.Columns.Count; i++)
    {
        Debug.Write(mytable.Columns[i].ToString() + " | ");
    }
    Debug.Write(Environment.NewLine + "=======" + Environment.NewLine);
    for (int rrr = 0; rrr < mytable.Rows.Count; rrr++)
    {
        for (int ccc = 0; ccc < mytable.Columns.Count; ccc++)
        {
            Debug.Write(mytable.Rows[rrr][ccc] + " | ");
        }
        Debug.Write(Environment.NewLine);
    }
}
public static void ResponsePrintTbl(DataTable mytable)
{
    for (int i = 0; i < mytable.Columns.Count; i++)
    {
        HttpContext.Current.Response.Write(mytable.Columns[i].ToString() + " | ");
    }
    HttpContext.Current.Response.Write("<BR>" + "=======" + "<BR>");
    for (int rrr = 0; rrr < mytable.Rows.Count; rrr++)
    {
        for (int ccc = 0; ccc < mytable.Columns.Count; ccc++)
        {
            HttpContext.Current.Response.Write(mytable.Rows[rrr][ccc] + " | ");
        }
        HttpContext.Current.Response.Write("<BR>");
    }
}

public static void printTblRow(DataSet myDataset, int RowNum)
{
    printTblRow(myDataset.Tables[0], RowNum);
}
public static void printTblRow(DataTable mytable, int RowNum)
{
    for (int ccc = 0; ccc < mytable.Columns.Count; ccc++)
    {
        Debug.Write(mytable.Columns[ccc].ToString() + " : ");
        Debug.Write(mytable.Rows[RowNum][ccc]);
        Debug.Write(Environment.NewLine);
    }
}
#endregion

I then I will call one of the above functions in the immediate window and the results will appear there as well. For example if I want to see the contents of a variable 'myDataset' I will call printTbl(myDataset). After hitting enter, the results will be printed to the immediate window



回答4:

public static void DebugDataSet ( string msg, ref System.Data.DataSet ds )
{
    WriteIf ( "===================================================" + msg + " START " );
    if (ds != null)
    {
        WriteIf ( msg );
        foreach (System.Data.DataTable dt in ds.Tables)
        {
            WriteIf ( "================= My TableName is  " +
            dt.TableName + " ========================= START" );
            int colNumberInRow = 0;
            foreach (System.Data.DataColumn dc in dt.Columns)
            {
                System.Diagnostics.Debug.Write ( " | " );
                System.Diagnostics.Debug.Write ( " |" + colNumberInRow + "| " );
                System.Diagnostics.Debug.Write ( dc.ColumnName + " | " );
                colNumberInRow++;
            } //eof foreach (DataColumn dc in dt.Columns)
            int rowNum = 0;
            foreach (System.Data.DataRow dr in dt.Rows)
            {
                System.Diagnostics.Debug.Write ( "\n row " + rowNum + " --- " );
                int colNumber = 0;
                foreach (System.Data.DataColumn dc in dt.Columns)
                {
                    System.Diagnostics.Debug.Write ( " |" + colNumber + "| " );
                    System.Diagnostics.Debug.Write ( dr[dc].ToString () + " " );
                    colNumber++;
                } //eof foreach (DataColumn dc in dt.Columns)
                rowNum++;
            }   //eof foreach (DataRow dr in dt.Rows)
            System.Diagnostics.Debug.Write ( " \n" );
            WriteIf ( "================= Table " + dt.TableName + " ========================= END" );
            WriteIf ( "===================================================" + msg + " END " );
        }   //eof foreach (DataTable dt in ds.Tables)
    } //eof if ds !=null 
    else
    {
        WriteIf ( "NULL DataSet object passed for debugging !!!" );
    }
} //eof method 

public static void WriteIf ( string msg )
{
    //TODO: FIND OUT ABOUT e.Message + e.StackTrace from Bromberg eggcafe
int output = System.Convert.ToInt16(System.Configuration.ConfigurationSettings.AppSettings["DebugOutput"] );
    //0 - do not debug anything just run the code 
switch (output)
{
    //do not debug anything 
    case 0:
        msg = String.Empty;
    break;
        //1 - output to debug window in Visual Studio       
        case 1:
            System.Diagnostics.Debug.WriteIf ( System.Convert.ToBoolean( System.Configuration.ConfigurationSettings.AppSettings["Debugging"] ), DateTime.Now.ToString ( "yyyy:MM:dd -- hh:mm:ss.fff --- " ) + msg + "\n" );
            break;
        //2 -- output to the error label in the master 
        case 2:
            string previousMsg = System.Convert.ToString (System.Web.HttpContext.Current.Session["global.DebugMsg"]);
            System.Web.HttpContext.Current.Session["global.DebugMsg"] = previousMsg +
            DateTime.Now.ToString ( "yyyy:MM:dd -- hh:mm:ss.fff --- " ) + msg + "\n </br>";
            break;
        //output both to debug window and error label 
        case 3:
            string previousMsg1 = System.Convert.ToString (System.Web.HttpContext.Current.Session["global.DebugMsg"] );
            System.Web.HttpContext.Current.Session["global.DebugMsg"] = previousMsg1 + DateTime.Now.ToString ( "yyyy:MM:dd -- hh:mm:ss.fff --- " ) + msg + "\n";
            System.Diagnostics.Debug.WriteIf ( System.Convert.ToBoolean( System.Configuration.ConfigurationSettings.AppSettings["Debugging"] ), DateTime.Now.ToString ( "yyyy:MM:dd -- hh:mm:ss.fff --- " ) + msg + "\n </br>" );
            break;
        //TODO: implement case when debugging goes to database 
    } //eof switch 

} //eof method WriteIf


回答5:

I've not tried it myself, but Visual Studio 2005 (and later) support the concept of Debugger Visualizers. This allows you to customize how an object is shown in the IDE. Check out this article for more details.

http://davidhayden.com/blog/dave/archive/2005/12/26/2645.aspx



回答6:

Give Xml Visualizer a try. Haven't tried the latest version yet, but I can't work without the previous one in Visual Studio 2003.

on top of displaying DataSet hierarchically, there are also a lot of other handy features such as filtering and selecting the RowState which you want to view.



回答7:

and if you want this anywhere... to be a helper on DataTable this assumes you want to capture the output to Log4Net but the excellent starting example I worked against just dumps to the console... This one also has editable column width variable nMaxColWidth - ultimately I will pass that from whatever context...

public static class Helpers
    {
        private static ILog Log = Global.Log ?? LogManager.GetLogger("MyLogger");
        /// <summary>
        /// Dump contents of a DataTable to the log
        /// </summary>
        /// <param name="table"></param>
        public static void DebugTable(this DataTable table)
        {
            Log?.Debug("--- DebugTable(" + table.TableName + ") ---");
            var nRows = table.Rows.Count;
            var nCols = table.Columns.Count;
            var nMaxColWidth = 32;

            // Column Headers

            var sColFormat = @"{0,-" + nMaxColWidth + @"} | ";
            var sLogMessage = string.Empty;
            for (var i = 0; i < table.Columns.Count; i++)
            {
                sLogMessage = string.Concat(sLogMessage, string.Format(sColFormat, table.Columns[i].ToString()));
            }
            //Debug.Write(Environment.NewLine);
            Log?.Debug(sLogMessage);

            var sUnderScore = string.Empty;
            var sDashes = string.Empty;
            for (var j = 0; j <= nMaxColWidth; j++)
            {
                sDashes = sDashes + "-";
            }


            for (var i = 0; i < table.Columns.Count; i++)
            {
                sUnderScore = string.Concat(sUnderScore, sDashes + "|-");
            }

            sUnderScore = sUnderScore.TrimEnd('-');

            //Debug.Write(Environment.NewLine);
            Log?.Debug(sUnderScore);

            // Data
            for (var i = 0; i < nRows; i++)
            {
                DataRow row = table.Rows[i];
                //Debug.WriteLine("{0} {1} ", row[0], row[1]);
                sLogMessage = string.Empty;

                for (var j = 0; j < nCols; j++)
                {
                    string s = row[j].ToString();
                    if (s.Length > nMaxColWidth) s = s.Substring(0, nMaxColWidth - 3) + "...";
                    sLogMessage = string.Concat(sLogMessage, string.Format(sColFormat, s));
                }

                Log?.Debug(sLogMessage);
                //Debug.Write(Environment.NewLine);
            }           
            Log?.Debug(sUnderScore);
        }
}