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 DataSet
s, DataRow
s, DataView
s and DataTable
s. 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
- You can select a
DataSet
, DataTable
, DataView
, or DataRow
.
- 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.
- If an object extends a
DataSet
, DataRow
, DataView
, or DataTable
it will be accessible (i.e. typed DataSet
s).
- You can apply multiple Data View Row State filters. For example, you can see Added and Deleted rows at the same time.
- When installed, appropriate registry entries are written which provide a friendlier description in the Visual Studio Add-In Manager Dialog.
- 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.
- 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.
- Download the source files.
- Build the solution.
- Close all instances of Visual Studio.
- Uninstall the current version of the DataSet Quick watch installed. (Add/Remove programs)
- Run the DataSetQuickWatchExtendedInstall.msi. This file is created when you perform the solution build. It will be in the DataSetQuickWatchSetup\Debug folder.
- 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:
- Create a helper class in a strongly named assembly. Install this assembly into the GAC.
- In the helper class create a method which calls the
WriteXML(OUTPUT_FILE,System.Data.XmlWriteMode.DiffGram
method.
- 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.
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.
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.
The properties for this custom action are:
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.
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);
}
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.