Click here to Skip to main content
Click here to Skip to main content

Enhanced DataSet Quick Watch

By , 20 Feb 2005
 

Sample Image - DSWatchEx1.png

Introduction

This add-in is essentially an update to Mohammed Barqawi's excellent DataSet Quick Watch add-in. Please reference the article for the original concept and code.

The add-in's implementation was great but notably didn't support typed datasets. I've added a few things to take the original ideas a little further and hopefully make life even easier to visualise a dataset whilst debugging.

What's New?

Typed DataSet support

This allows all Typed DataSets (directly inherited from System.Data.DataSet) to be used with the add-in. This also works with typed DataTables and DataRows.

Support for DataTables and DataRows

This allows you to select a table or row (in code) and load the dataset (selecting that table or row in the output).

Row Filter Support

A free text row filter and 'DataViewRowState' filter has also been added to help with debugging. This functions on a per table basis.

Visual Enhancements

The DataSet Watch form has been amended to use a custom 'EnhancedGrid' control to provide filtering and a slightly more 'colourful' output. If you're not keen on the look of the grid then you can easily change it by changing the EnhancedGrid UserControl.

I didn't quite get round to adding the support for user preferences!

Using the code

Debugger Expressions

The original concept still stands, but I've made a few amendments to the way we get and check debugger expressions. I refactored the construction of each expression to work based on the input language:

    private string GetEvaluationExpression(string type, object selectedObject, 
                    string propOrMethod, string SourceType)
    {
        switch (SourceType)
        {
            case LangCSharp:
            {
                return "(" + type + ")" + selectedObject + propOrMethod;
            }
            case LangVB:
            {
                if (type == "int")
                    type = "System.Int32";
                    //HACK to cope with language differences
                return "ctype(" + selectedObject + ", " 
                                + type + ")" + propOrMethod;
            }
            default :
            {
                throw new ApplicationException("Invalid Source Type : " 
                                            + "Expected 'cs' or 'vb'");
            }
        }
    }

Where str (the selected text in the debugger) == "myDataTable", the line below will assign a language-specific debugger expression string to getTableNameFromTableExpression:

getTableNameFromTableExpression = 
   GetEvaluationExpression(TypeDataTable, str, ".TableName", fileExtension);
  • C# - System.Data.DataTable)myDataTable.TableName
  • VB - ctype(System.Data.DataTable, myDataTable).TableName

This particular expression is used to get the tablename from a selected DataTable.

Typed DataSets

The support for typed datasets comes in when we evaluate an expression that returns an unexpected type. This will happen because the debugger returns the 'actual' type of the expression you've selected - e.g., MyNamespace.MyTypedDataSet.MyTableRow.

If you selected something other than a DataSet, DataTable or DataRow (or anything that derives directly from any of these), the ExpressionHasError method would find the text "error:" in the expression's value.

In the case we return a typed data object (and we return the type name), we then find the base type and evaluate the expression again... If it's a typed dataset, table or row, then we should find the correct (System.Data...) type second time around.

    // Calling code.....  Filtering down -
    // checking for DataSet, then DataTable, then DataRow

    //Check which worked!
    if (ExpressionHasError(exprDataSet, "{System.Data.DataSet}", str))
    {
        //Check for DataTable
        if (ExpressionHasError(exprDataTable, "{System.Data.DataTable}", str))
        {
            //Check for DataRow
            if (ExpressionHasError(exprDataRow, "{System.Data.DataRow}", str))
            {
                MessageBox.Show("This is not a DataSet, DataTable or DataRow!",
            "DSWatch",MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }


    //.....

    private bool ExpressionHasError(Expression expr, 
                 string type, string originalContext)
    {
        EnvDTE.Debugger debugger = applicationObject.Debugger;

        if (type != null)
            if (expr.Value.IndexOf("error:")>-1)
                return true;
            else
            {
                if (expr.Value != type)
                {
                    //Check for base type (only going one level down 
                    //   - so assume here that every 'typed' dataset
                    //is a direct descendent of System.Data.DataSet

                    //need to remove any quotes if we're in a recursive call
                    Expression baseExpression = 
                      debugger.GetExpression(originalContext + 
                      ".GetType().BaseType.Name" , true, 500);
                    string val = baseExpression.Value.Replace("\"", String.Empty);
                    string subType = type.Substring(type.LastIndexOf(".") 
                                          +1).Replace("}", String.Empty); 
                    return (val != subType);
                }
                else
                    //All is OK
                    return false;
            }
        else
            return expr.Value.IndexOf("error:")>-1;
    }

Selecting specific rows

If we've selected a row in the debugger by a variable: myRow or with an indexer: myDataSet.Tables[0].Rows[0], we know we can find the ordinal position of the row (in the table) via the rowID property. We can then use this information in the output form to select the appropriate row (and table).

Row Filtering

Row Filtering

This works with a combination of standard DataView filtering - using a free text row filter, and a DataViewRowState filter (useful to show all rows in a particular state). The following applies a combination of both filters.

    private void ApplyFilter(bool showAll)
    {
        try
        {
            if (_dataSource == null)
                return;

            //Filter the contents of the grid
            if (showAll || (this.rowStateFilter.SelectedIndex == 0 && 
                            this.rowFilterExpression.Text == String.Empty))
                _view = _dataSource.DefaultView;
            else
            {
                _view = new DataView(_dataSource);
                if (this.rowStateFilter.SelectedIndex != 0)
                    _view.RowStateFilter = 
                      (DataViewRowState)Enum.Parse(typeof(DataViewRowState), 
            this.rowStateFilter.SelectedItem.ToString(), true);

                _view.RowFilter = this.rowFilterExpression.Text;
            }
            this.grid.DataSource = _view;
            if (this.FilterChanged != null)
                this.FilterChanged(this.grid, 
                     new FilterChangedEventArgs(_dataSource, 
                     _view.Count, _dataSource.Rows.Count - _view.Count));

            this.grid.Refresh();
        }
        catch (Exception ex)
        {
            MessageBox.Show(String.Format("There was a problem" + 
               " applying the row filter\n\n{0}", ex.Message), 
               "Row Filter", MessageBoxButtons.OK, 
               MessageBoxIcon.Exclamation);
        }

    }

The EnhancedGrid UserControl defines a FilterChanged event, passing context information to allow the parent form to alter the text in its Status Bar.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

CodeBureau - Matt Simner
Software Developer (Senior) Codebureau
Australia Australia
Member
Started with COBOL/CICS/DB2 - ended up with C#/ASP.NET. I'm a half-geek (or so my wife tells me!)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionError : This is not a dataset or datatable or datarowmemberDilip Baboo12 Mar '09 - 8:32 
Hi there ,
I am using VS2003 and I get an error "This is not a dataset or datatable or datarow" on debugging and using the Dataset Quick Watch feature. I am using System.Data.DataSet test = new DataSet();
GeneralVisual Studio 2005 Framework 2.0membericedragon4 May '07 - 3:52 
Just wondering will this be upgraded? I like how simplified this is compare to the rest.
Generalsomething for VS 2005memberfadee2 Jan '07 - 20:21 
People, check out http://www.codeproject.com/dotnet/DataSet_Watch2.asp
 
-------------------
Therez No Place like ... 127.0.0.1

GeneralGOOD WORKmemberEIHABWADY6 May '06 - 4:16 
Good Work Thank yRose | [Rose] ou
 
EiHAB WADY
Generalfix to DataTable not in DataSetmembersharaabi14 Dec '05 - 23:11 
on file
Connect.cs
fix three things:
1
move out the variables:

string str;
string fileExtension ;
EnvDTE.Debugger debugger;
 
public void Exec(string commandName, EnvDTE.vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
...

 
2
replace
_DatasetWatchFrm.BuildXml(exprDataSet.Value, selectedTableName, selectedRowID);
 
with
 
try
{
_DatasetWatchFrm.BuildXml(exprDataSet.Value, selectedTableName, selectedRowID);
}
catch(System.Exception ex) // added by rans
{

System.Data.DataSet _dataSource = new System.Data.DataSet("Container");
System.Data.DataTable myDataTable = new DataTable("ParentTable");
DataColumn myDataColumn;
DataRow myDataRow;
for (int i=0; i
 
3
add function:
private string GetExpression(string s)
{
return debugger.GetExpression(GetEvaluationExpression(TypeDataTable, str, s, fileExtension),true,500).Value;
}

 
I tested it only in VB.net, but it seems good also for C#...
Big Grin | :-D

GeneralRe: fix to DataTable not in DataSetmemberAaronVisser15 Dec '05 - 13:59 
Hi, look slike you're missing a bunch of data from the for loops. Could you fix please?
 
Thanks!
GeneralRe: fix to DataTable not in DataSetmemberroberto galbiati26 Feb '06 - 22:49 
hi
code is not missing.
Codeproject layout "hides" missing code.
Try "view source" from your browser, and code appears!!!
 
I've discovered this only today.
 
Roberto
GeneralERROR: Not a dataset, datatable or datarowmemberIhor Bobak1 Dec '05 - 8:46 
When I am trying to view the contents of a dataset, it always displays me a dialog window that this is not a dataset, datatable or datarow. I am using your example. Whats wrong?
GeneralDoesn't work on Typed DataSet..memberEran S3 Aug '05 - 4:11 
When using the tool, I couldn't open typed DS for watching, although they inherit directly from System.Data.DataSet. the "This is not a DataSet..." error is shown.
 
However, viewing typed DataTable and DataRow of the typed DataSet is working.
 
Have you encountered this problem?Suspicious | :suss:
GeneralRowStateFilter does not workmemberPinx9 Jun '05 - 2:35 
The RowStateFilter combobox seems like a great feature, but it does not work. Because you convert the dataset to XML and read it back in into a new dataset, all the rows have rowstate Added.
If you could convert the original dataset into a DiffGram and read that in, maybe you could preserve the original row states.

GeneralMethod not found : void System.Windows.Forms.set_location(...)membernghadiri8 Jun '05 - 18:31 
It is working fine with WinForms,
but when I debug asp.net , the above error is shown.
Why?
 
Nasser
GeneralInvalid Data at root levelmemberCKurmann29 Mar '05 - 20:17 
Hi All,
 
I too find this and the original Tool a must have. However I'm having problems with some Datasets. I Often get the following Error Message from DSwatch "The Data at the root level is Invalid. Line 1, Position 1"
 
Whats really strang is that it seems to have something to do with the amount of data I try to load into the Datatables in the Dataset. For example at the moment I am loading a larger Adress Database into a table with +5000 records. If I load 113 or less DSwatch works. If I load 115 or more it doesn't. If I load 114 it sometimes works and sometimes doesn't. I am of course not changing any adresses in this time...
 
Any Idea of what could be causing the above error message?
 
Greetings from Switzerland
Christian
GeneralRe: Invalid Data at root levelmemberMatt Simner6 Apr '05 - 3:32 
Hmmm, interesting. You're the second person to have a problem with volumes of data.
 
I wonder if there are some practical limitations on using debugger expressions to deserialise objects. I'll have a look into this as I've had the 'data at root level' message myself a few times. I think in those cases it was down to me selecting the wrong text in the debugger (i.e. not an instance of a DataSet, DataTable or DataRow).
 
I'll try and track it down...
 

GeneralRe: Invalid Data at root levelmemberttrfanatic12 Apr '05 - 19:30 
I have received this myself many times and I have tracked it down in my case to be related to me trying to view a datatable that is not associated with a dataset. In other words, I have instantiated a datatable by itself rather than using a dataset. Hope this helps...
GeneralRe: Invalid Data at root levelmemberAngelOfBinolino4 May '05 - 2:44 
Hi All,
 
I have this problem with a datatable with 8500 rows, too.
 
While debugging the code of "Enhanced DataSet Quick Watch", I found out what's wrong:
 
There is a timeout while getting the XML-code of the datatable.
 
Just wanted to report this, 'cause I have too less time to do the futher work.
 
Bino
GeneralRe: Invalid Data at root levelmemberfrasse5313 Jun '05 - 1:55 
Hi,
 
I have had this problem with the other version aswell. I have never figured out what is wrong. What would help is if it was possible to view the XML as text only atleast.
 
-----------------------------
Fredrik Andersson (Coder)
Generaldoesnt work with dataviewssusskevin herring4 Mar '05 - 3:10 
this is a superb bit of code, very useful. could you make it work with dataviews too pls?
 
ta
Generalvery kewl but doesn't workmemberMaestrocity2 Mar '05 - 12:01 
With my doubly subclassed dataset object.
GeneralRe: very kewl but doesn't workmemberMatt Simner3 Mar '05 - 23:30 
Thanks - I knew I should have gone the extra mile and enabled a more flexible recursive type resolution!
GeneralRe: very kewl but doesn't workmemberPinx8 Jun '05 - 4:10 
Any chance on an update to add this feature???
GeneralGDI+ ErrormemberBig Cheese23 Feb '05 - 4:48 
Hi,
 
I've been using the original version of this add-in for quite some time and find it indespensible.
 
I saw your updated version adding many more options, so I installed it.
 
When I invoke your add-in, the XML tab displays the data just fine, but when I click the DataSet tab, I get the following error: ExternalException A generic error occurred in GDI+
 
Then the DataSet tab has a large red x through the entire box.
 
I'm using VS2003.
 
Any idea what may be causing this?
 
Thx.
Andy Jacobs
GeneralRe: GDI+ ErrormemberMatt Simner23 Feb '05 - 16:39 
Ouch! Sorry you're having problems
 
I have to admit to not ever seeing this error (during development). I made sure I didn't add any 3rd party controls or any other dependencies, but I did introduce a user control (with a DataGrid on it), which is used in place of the simple grid in the original addin.
 
I've had a quick google and most occurrences of this error seem to be around saving images (which I'm not doing). Other problems seem to be around resizing a datagrid on a form (which is more likely to be the case). That error only occurred on specific machines though. The only suggestion offered was checking video drivers (which isn't terribly helpful). If I experience the problem or find an answer I'll post it here....
GeneralRe: GDI+ ErrormemberBig Cheese24 Feb '05 - 5:22 
Matt,
 
Thanks for your quick response.
 
You know, I checked my video driver and found it was from 2003. So just for the hell of it, I installed the newest version.
 
The add-in works perfectly now.
 
So all that tech support yada yada does work sometimes!
 
Thx.
Andy

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 21 Feb 2005
Article Copyright 2005 by CodeBureau - Matt Simner
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid