Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Extended DataSet Quick Watch

3.00/5 (2 votes)
3 Nov 20064 min read 1   472  
An extended version of the DataSet Quick Watch application.

Image Missing

Introduction

My programming team has been using the original DataSet Quick Watch (Author mohammed barqawi) since its inception. What a wonderful tool! Since we use the Add-In everyday a few enhancements came about. For example, viewing deleted rows, applying filters, support for DataSets, DataRows, DataViews and DataTables. We found the Enhanced DataSet Quick Watch (Author Matt Simner) but the enhanced version does not allow you to apply a data view row state filter. For example, you cannot view deleted rows using the Enhanced DataSet Quick Watch. I liked Matt's idea and wondered why his row state filter did not work.

NOTE: I realize Visual Studio 2005 includes Visualizers, but my team will not be migrating to future versions of Visual Studio for several years. So please don't post anything about Visualizers in VS 2005, as I know they exist but am not using VS 2005. Thanks!

What's New

  1. You can select a DataSet, DataTable, DataView, or DataRow.
  2. When selecting a DataTable, DataView, or DataRow the tab page containing the associated table becomes the current tab when the tab of DataTable's displays.
  3. If an object extends a DataSet, DataRow, DataView, or DataTable it will be accessible (i.e. typed DataSets).
  4. You can apply multiple Data View Row State filters. For example, you can see Added and Deleted rows at the same time.
  5. When installed, appropriate registry entries are written which provide a friendlier description in the Visual Studio Add-In Manager Dialog.
  6. The state of a row determines the color of the row. For example, deleted rows display in red, new rows appear in green and modified rows appear in yellow.
  7. The XML tab was removed to decrease memory footprint.

Quick Install Guide

For those not concerned with code details and want to install here are some installation instructions.

  1. Download the source files.
  2. Build the solution.
  3. Close all instances of Visual Studio.
  4. Uninstall the current version of the DataSet Quick watch installed. (Add/Remove programs)
  5. Run the DataSetQuickWatchExtendedInstall.msi. This file is created when you perform the solution build. It will be in the DataSetQuickWatchSetup\Debug folder.
  6. Create a c:\Temp folder if you do not have one.
For those wanting more details please read-on.

Background

Before a debugged DataSet can be visualized it must be written out somewhere. The original DataSet Quick Watch writes the contents of the DataSet inside the EnvDTE.Debugger object. The enhanced version uses the DataSet's WriteXML() method.

The WriteXML() method has seven overloads. We need to call the overloaded version which will include the DiffGram. The DiffGram includes original and current row values. By including original and current values we can view modified and current values of the same row. The overloaded method version we need has the signature WriteXML(string,System.Data.XmlWriteMode). The challenge is you cannot call the appropriate overloaded version from EnvDTE.Debugger object. When you try to call this method version from the EnvDTE.Debugger object, you receive the error error: arguments do not match parameters for function 'this.dsMain.WriteXml'.

How can we call the appropriate method overload which allows us to view all row states in a DataSet? My solution consists of the following:

  1. Create a helper class in a strongly named assembly. Install this assembly into the GAC.
  2. In the helper class create a method which calls the WriteXML(OUTPUT_FILE,System.Data.XmlWriteMode.DiffGram method.
  3. Have the DataSet Quick Watch load the helper class. Once the helper class is loaded, call the method which writes the contents of the highlighted DataSet including the DiffGram.

Using the code

The helper class, DataSetQuickWatchHelper, includes the following method. This method is called from the Add-Ins Connect.Exec method.
C#
public static void WriteDebuggedDataSet(object prDataSet)
{
    DataSet rDS = prDataSet as DataSet;

    if (rDS == null)
    {
        return;
    }
    rDS.WriteXml(XML_PATH,System.Data.XmlWriteMode.DiffGram);
    rDS.WriteXmlSchema(XML_SCHEMA_PATH);
}
The DataSetQuickWatchHelper class is installed into the GAC by extending the System.Configuration.Install.Installer class. The extending class, DataSetQuickWatchHelperInstaller overloads two methods.
C#
public override void Install(IDictionary stateSaver)
{
    base.Install (stateSaver);

    string sAssemblyPath = base.Context.Parameters["name"].ToString();
    System.EnterpriseServices.Internal.Publish rPublish = 
        new System.EnterpriseServices.Internal.Publish();
    rPublish.GacInstall(sAssemblyPath);
}

public override void Uninstall(IDictionary savedState)
{
    string sAssemblyPath = base.Context.Parameters["name"].ToString();
    System.EnterpriseServices.Internal.Publish rPublish = 
         new System.EnterpriseServices.Internal.Publish();
    rPublish.GacInstall(sAssemblyPath);
    
    base.Uninstall (savedState);
}

In the DataSetQuickWatchSetup project, a custom action was defined which calls these methods.

Image Missing

The properties for this custom action are:

Image Missing

The DataSetQuickWatch class uses the following code in the Connect.Exec method to access the DataSetQuickWatchHelper class. As you can see, the System.Activator.CreateInstance method is invoked. This method loads the DataSetQuickWatch helper class from the GAC. If the assembly is created successfully, then the DataSetQuickWatch.WriteDebuggedDataSet method is invoked.

C#
// Load this assembly into the system.  
// NOTE:  This assembly is installed in the GAC.
//
string sCreateClass = "System.Activator.CreateInstance(" + '"' + 
       HELPER_CLASS_ASSEMBLY + "," + HELPER_CLASS_VERSION + 
       "," + HELPER_CLASS_CULTURE + "," + HELPER_CLASS_KEY + 
       '"' + "," + '"' + HELPER_CLASS_NAMESPACE + 
       HELPER_CLASS_CLASS  + '"' + ")";

EnvDTE.Expression rWriteExpression = 
   rDebugger.GetExpression(sCreateClass,true,nGetExpressionTimeout);
if (rWriteExpression.Value.IndexOf("error:")>-1)
{
    MessageBox.Show("Error loading Assembly '" + 
                    Application.ExecutablePath + 
                    "'","Error Information",
                    MessageBoxButtons.OK,MessageBoxIcon.Error);
}

//
// Write the highlighted DataSet to XML including a Diffgram.
//
string sLoadLocalDataSet = HELPER_CLASS_NAMESPACE + "." + 
                           HELPER_CLASS_CLASS + "." + 
                           HELPER_CLASS_METHOD + "(" + 
                           sDataSetObjectPath + ")";
rWriteExpression = rDebugger.GetExpression(sLoadLocalDataSet,
                   true,nGetExpressionTimeout);

Points of Interest

When setting a row filter, if the field type is a string you will need to place the value desired in quotes. For example, Name='Bill'.

My company uses a grid component from Infragistics. To ensure this add-in works without a custom grid component, I created a version using the DataGrid class installed with .NET 1.1.  This is the version included.

I did not test how the .NET DataGrid class displays related tables. For example, the Infragistics grid will display a plus-sign (+) next to a row to display child rows. Child rows will also display in the appropriate colors. I'm not sure how the .NET DataGrid class handles related rows/tables. Feel free to modify to display appropriately.

The DataSet's XML and XSD are written to the C:\Temp folder. Make sure this folder exists or modify the code to place in an another folder. I got lazy and did not check if the folder already exists. I assume everyone has a C:\Temp folder.

History

Any feedback is appreciated.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here