none
Enumerate Data Objects in .NET RRS feed

  • Question

  •  

    I've been studying .Net programming for a while now, but still find the data objects to be a bewildering mess.

     

    Coming from a VBA background, I expect and hope that everything is still contained in enumerable collections.

     

    I have been successful enumerating a couple of the data objects in .Net, but have had absolutely no luck with

    some of them, despite hours of searching and despite attending the expensive and useless 4995 Programming .Net class.

     

    Can someone please tell me if all the data objects in .Net are contained in enumerable collections? If so, please

    provide the simplest Visual Basic code required to do this.

     

    DataSet, TableAdapter, DataTable especially.

     

    I code in and read Visual Basic only. Please, no code in C#.

     

    Many thanks.

    Saturday, February 2, 2008 8:12 PM

Answers

  • Hello,

     

    I'm coming back .

     

    I've never done to iterate through all datasets in a project but i know it's possible : you have only to use classes which are in System.Reflection

    In the BOL, you can read :

    The System.Reflection namespace contains classes and interfaces that provide a managed view of loaded types, methods, and fields, with the ability to dynamically create and invoke types.

     

    I know that for an assembky, you may find all the members,the fields of the classes which are in the assembly.

    But i never have done it, so i can't help you

     

    Maybe a moderator or a specialist about this question could better help than me

    Or see this forum ( where they are speakin about refelection ):

    http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=39&SiteID=1

     

    I will go on my search because this subject is very interesting for me

     

    Have a nice day

     

    Sunday, February 3, 2008 9:45 AM
  • Thanks for the clarifications on what you're looking for.

     

    There is no high-order collection of DataSet objects.  It's up to your program to create and manage whatever collection of DataSets it needs - very often, all that a program needs is a single instance of a single DataSet.

     

    If, for some reason, your code doesn't know what DataSets are in the assembly, you can use reflection to examine the assembly and find all the types derived from System.Data.DataSet.  But that's a collection of DataSet types, not a collection of DataSet objects.

     

    In most ADO code you'll find, TableAdapters (or table adapters, as I like to call them, to remind myself that they aren't actually derived from a framework class) are created by whatever method needs one, e.g.

     

    Code Snippet

    private void MyMethod()

    {

       MyApplicationNamespace.MyDataSetTableAdapters.SomeTableAdapter t = new MyApplicationNamespace.MyDataSetTableAdapters.SomeTableAdapter();

       t.Fill(MyDataTable);

    }

     

    Ugly code, but at least most of it's written by IntelliSense.

     

    The thinking, I guess, is that the performance cost of creating a table adapter object is small enough that it's not worth the maintenance overhead you'd incur by building a collection of them.  (I'm don't know why they're not just implemented as static classes.  As my mom used to say, I'm sure there's a perfectly good explanation for this.)  At any rate, there's no collection of table adapters that you can enumerate unless you made it yourself.

    Sunday, February 3, 2008 12:53 PM

All replies

  • Look at the documentation for DataSet.Tables, DataTable.Columns, and DataTable.Rows.  What do you need to know that this documentation doesn't tell you?

    Saturday, February 2, 2008 9:08 PM
  • I need to know how to enumerate these objects, as described in my above post. I have read carloads of documentation, none of which chart the hierachy of any object model(s) for the data objects I mentioned.

     

    As an example, the DAO object model is well documented. I can tell by glancing at the data access hierarchy diagram exactly how to enumerate the collections within. I can find no such diagram for the data access objects in .Net.

     

    If you could point me to a good diagram, I'd appreciate it.

     

    Saturday, February 2, 2008 9:21 PM
  • Hello,

     

    Could you give an example of your enumeration of a couple data objects ?

    It would be useful to know what you want exactly.

    If we take the example of DataTable, you have some well-known collections like DataColumns,DataRows and so on.

    Some are in the namespace System.Data ( DataTable,DataColumns,DataRows and so on) others are in System.Data.Common ( as DataColumnMapping)

     

    For example  you want to enumerate all the DataColumns of a DataTable named dt:

    Dim columns As DataColumnCollection =  dt.Columns;

    Console.WriteLine("The DataTable has {0} Columns",dt.Columns.Count)

    For Each ( DataColumn Column in columns )

           Console.WriteLine("Name          : {0}",Column.ColumnName)    ' name of the column

           Console.WriteLine("Caption        : {0}",Column.DataType)    'Type of data stored in the column

           Console.WriteLine("AllowDBNull : {0}",Column.AllowDBNull)     ' if true the column may contain null values

           Console.WriteLine("AutoIncrement : {0}",Column.AutoIncrement) 

    Next

     

    But you have to look at all properties of DataColumn and to repeat the code for each property ( about 30 or 40 properties some are useless : autoincementseed if the column is not autoincremented )

    You have to foresee some If .. Then to avoid to get null or without use properties

     

    Can someone please tell me if all the data objects in .Net are contained in enumerable collections?

     

    Of course, not

     

    I hope this post will help you

    Don' forget that before using a class, it's better to have well understood all the members of this class. Moreover, many members of a class are using other classes that you will have to study at least to know that those classes are existing

     

    Have a nice day

    Saturday, February 2, 2008 9:22 PM
  • Sure Papy, and thank you.

     

    In this example, I am able to enumerate DataTables in the dsEmployees DataSet:

     

    Dim ds As New dsEmployees

    Dim dt As dsEmployees.EmployeesDataTable

     

    For Each dt In ds.Tables

    Debug.Print("Table: " & dt.TableName)

    Next dt

     

    I am unable to enumerate all DataSets in a project.

    I am unable to enumerate all DataTables in all DataSets in a project.

    I am unable to understand whether a TableAdapter is part of any collection, and if so, which one.

     

    Thank you.

    Saturday, February 2, 2008 9:31 PM
  • Hello,

     

    If you have a look on the documentation of DataAdapter , you will that : Represents a set of SQL commands and a database connection that are used to fill the DataSet and update the data source

    and a liitle latter

    The DataAdapter serves as a bridge between a DataSet and a data source for retrieving and saving data

     

    I found a good definition in the excellent book of David Sceppa (Programming Microsoft ADO.NET 2.0 Core Refrence):

    "DataAdapter class acts as a bridge between the connected and disconnected halves of the ADO.NET object models.

    In the connected part, you will find Connection,Command,Parameter,DataReader which interact with the database

     

    In the disconnected part, you have Dataset,datatable,dataview,datacolumn and so on.

     

    If i have well understood ADO.NET,,the main role of DataAdapter is :

    - to get data from a database and fill dataset/datable with these data

    - when you have modified these data, it's the DataAdapter which transmits these modified data to update one or several tables in the database ( modify = insert,update or delete )

    - it's DataAdapter which works for checking if the data sent from the prog were not modified  by others users...

     

    I have found only a collection for DataAdapter : TableMappings

    see  http://msdn2.microsoft.com/en-us/library/system.data.common.dataadapter.tablemappings(VS.80).aspx

    TableMappings links the columns names of a table of a dataset with the column names of a datatable

     

    In your leading post, you were speaking about ADO ( VB 6 ).

    We have ADO.NET from VB 2003 and Famework 1.1 and i think that was an error from Microsoft to use two expressions to similar for 2 technologies which are so different in the logic ( sorry , i've not found the correct translation in english )

    I've struggled with DAO and ADO ( in VC++ and VB ) .I had less difficulties with ADO.NET but i had to forget everything i have learnt with ADO ( VB 6)

     

    I hope that my poor english will not be a discomfort for my explanation

     

     

    Saturday, February 2, 2008 10:15 PM
  •  

    Hello Papy,

    Your English is quite good and your explanation and thoughts are quite clear.

     

    As I understand it then, it appears that the TableAdapter is not added to any collection when it is created.

     

    I am able to iterate through the data objects below the level of the DataSet.

     

    I've narrowed my confusion down to not understanding which collection contains the DataSets collection, if any.

     

    If your or anyone could please describe how to iterate through all DataSets in a project, I'd be very happy and could

    continue on learning from there.

     

    Thanks.

    Sunday, February 3, 2008 3:00 AM
  • Hello,

     

    I'm coming back .

     

    I've never done to iterate through all datasets in a project but i know it's possible : you have only to use classes which are in System.Reflection

    In the BOL, you can read :

    The System.Reflection namespace contains classes and interfaces that provide a managed view of loaded types, methods, and fields, with the ability to dynamically create and invoke types.

     

    I know that for an assembky, you may find all the members,the fields of the classes which are in the assembly.

    But i never have done it, so i can't help you

     

    Maybe a moderator or a specialist about this question could better help than me

    Or see this forum ( where they are speakin about refelection ):

    http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=39&SiteID=1

     

    I will go on my search because this subject is very interesting for me

     

    Have a nice day

     

    Sunday, February 3, 2008 9:45 AM
  • Thanks for the clarifications on what you're looking for.

     

    There is no high-order collection of DataSet objects.  It's up to your program to create and manage whatever collection of DataSets it needs - very often, all that a program needs is a single instance of a single DataSet.

     

    If, for some reason, your code doesn't know what DataSets are in the assembly, you can use reflection to examine the assembly and find all the types derived from System.Data.DataSet.  But that's a collection of DataSet types, not a collection of DataSet objects.

     

    In most ADO code you'll find, TableAdapters (or table adapters, as I like to call them, to remind myself that they aren't actually derived from a framework class) are created by whatever method needs one, e.g.

     

    Code Snippet

    private void MyMethod()

    {

       MyApplicationNamespace.MyDataSetTableAdapters.SomeTableAdapter t = new MyApplicationNamespace.MyDataSetTableAdapters.SomeTableAdapter();

       t.Fill(MyDataTable);

    }

     

    Ugly code, but at least most of it's written by IntelliSense.

     

    The thinking, I guess, is that the performance cost of creating a table adapter object is small enough that it's not worth the maintenance overhead you'd incur by building a collection of them.  (I'm don't know why they're not just implemented as static classes.  As my mom used to say, I'm sure there's a perfectly good explanation for this.)  At any rate, there's no collection of table adapters that you can enumerate unless you made it yourself.

    Sunday, February 3, 2008 12:53 PM
  •  

    Thanks, both of you.

     

    Robert, I somehow doubt there is a perfectly "good" explanation for it. The explanation is perfectly "something", though, I am sure. At any rate, I think all these objects should be added to static collections when created. The data objects are confusing enough without having such important things floating out in the ether.

     

    It's a rather confusing mess, considering that in the past, everything was all orderly. I am slowly getting the hang of it.

     

    Papy, for my own enlightenment mostly, but not least for your benefit, I have done some exploring in the System.Reflection class and am able to iterate through the names of the BaseTypes, at least.

     

    Code Snippet

     

    Imports System.Reflection

     

    Public Class Form1

     

    Private Sub cmdInspectAssy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdInspectAssy.Click

    InspectModules()

    End Sub

     

    Private Sub InspectModules()

    Dim assy As Assembly = Assembly.Load("NorthwindApplication")

     

    'Search assembly for modules

    For Each m As Reflection.Module In assy.GetModules()

    Debug.Print("Module Name: " & m.Name)

    Next m

    ListDataSets(assy)

    End Sub

     

    Private Sub ListDataSets(ByVal assy As Assembly)

     

    Debug.Print("DataSets:")

     

    'Search classes which inherit from DataSet.

    For Each ds As Type In assy.GetTypes

    If ds.BaseType.Name = "DataSet" Then

    Debug.Print(" " & ds.Name)

    End If

    Next ds

    ListDataTables(assy)

    End Sub

     

    Private Sub ListDataTables(ByVal assy As Assembly)

     

    Debug.Print("DataTables:")

     

    'Search classes which inherit from DataTable.

    For Each dt As Type In assy.GetTypes

    If dt.BaseType.Name = "DataTable" Then

    Debug.Print(" " & dt.Name)

    End If

    Next dt

    ListTableAdapters(assy)

    End Sub

     

    Private Sub ListTableAdapters(ByVal assy As Assembly)

     

    Debug.Print("TableAdapters:")

     

    'Since there is no base type, search for the namespace.

    For Each ta As Type In assy.GetTypes

    If ta.FullName Like "*" & "TableAdapters.*TableAdapter" Then

    Debug.Print(" " & ta.Name)

    End If

    Next ta

    End Sub

     

    End Class

     

     

    This code results in the following output for me:

     

    Module Name: NorthwindApplication.exe

    DataSets:

         dsDPMCustomers

         dsDPMEmployees

    DataTables:

         CustomerDataTable

         CustomerSiteDataTable

         EmployeeDataTable

         EmployeeAddressDataTable

    TableAdapters:

         CustomerTableAdapter

         CustomerSiteTableAdapter

         EmployeeTableAdapter

         EmployeeAddressTableAdapter

     

    So, I got what I wanted out of the deal, and was dragged kicking into a class I didn't care anything about before.

    System.Reflection can peek into any assembly, however, and return a huge amount of information about it. It's easy

    to envision cascading listboxes filled with DataSets, their DataTables and TableAdapters.

     

    I was able to output most of the objects in a hierarchical list, but struggled with getting the TableAdapters hung onto the list in their proper places in the hierarchy, so I just grouped everything in the end. String manipulation is a pain sometimes...

     

    For more fun, one might include the DataColumns and even fill a DataSet and enumerate some Rows.

     

    Thanks again for you help. I've learned a lot.

    Monday, February 4, 2008 6:06 AM
  • Hello,

     

    Thank you very much for your piece of code you posted.

    I will examin with much attention.

    I never had time to explore System.Reflection, but i will have to do because i'm willing to try to get the certification 70-536 which is using it.

     

    Good continuation for you

     

    Have a nice day

    Monday, February 4, 2008 6:20 AM
  • Oh, when my mom said "I'm sure there's a perfectly good explanation for this," what she meant was "Don't even think about coming up with some kind of lame excuse, because I will gut you like a fish."

     

    That's a pretty nifty bit of programming you've done there.  You now know about as much about reflection as I do.  (Maybe more.)  Just be careful:  types aren't instances.  For example, any table adapter that implements a GetData method will return an instance of a strongly-typed DataTable that isn't referenceable through the strongly-typed namespace.

     

    > At any rate, I think all these objects should be added to static collections when

    > created. The data objects are confusing enough without having such important things

    > floating out in the ether.

     

    I don't agree.  There are many circumstances under which automatically maintaining a global static collections of these objects is unhelpful.  The GetData example above is one.  Here's another:

     

    I'm building an application right now that generates a DataSet dynamically off of metainformation stored in another DataSet.  I can have multiple versions of my configuration DataSet, and multiple DataSets containing my data.  A monolithic static collection of all the DataSets that my application has created at any given time is not useful to me:  I need two separate collections:  one containing the DataSets that house the data, and one containing the configuration data sets for each version. 

     

    These data sets can get pretty big, and so I've implemented my configuration collection as a priority queue that discards the least-recently-used DataSet when memory runs low.  Also, my configuration datasets are strongly-typed, and my data datasets (which are dynamically generated off of the configuration at runtime) aren't.

     

    The last thing this program needs is some global collection that I have to remember to negotiate with before I can throw something away and be sure that it really gets destroyed.

     

    It's also important to be able to create DataTable objects that don't live inside of DataSets.  I do this all the time.  For instance, if you have a collection of objects, and you want the user to be able to display and/or edit their properties in a DataGridView, and you want to support sorting and filtering, the "right" way to do this is to extend your collection to implement IBindingList.  I put "right" in scare quotes because even if you know how to do it (and you don't, unless you've bought a book that tells you how to, because you're not going to learn it from the documentation),  implementing IBindingList is an unbelievable pain in the ***.

     

    Here's what's not an unbelievable pain in the ***:  creating a DataTable, adding DataColumns that contain property values, and adding a RowChanged event handler to update the underlying object when something like a user interface changes the contents of a row.  If you do this, you can bind a DataGridView to it in a second, and the DGV will support sorting and filtering, because DataTable supports sorting and filtering (and exposes those methods through IBindingList).

     

    The ADO object hierarchy is pretty daunting to learn.  But the fact that it doesn't hold your hand also gives it a lot of flexibility and power.

    Monday, February 4, 2008 9:04 AM
  •  

    Thanks for the interesting scenarios you described. I guess I might have said that my opinion is that Microsoft should have made the model much, much simpler...and added all those much, much simpler objects to collections.

     

    Even with COM objects there were nine ways to skin any cat. There were some limitations, but innovative people found ways to get things done every single time. In the above "much, much simpler" scenario, all the objects would be enumerable so I could quickly find, instantiate and use them. Things like adding parameters to queries, building and sorting lists of the data objects, etc.

     

    I guess having them all visible in the IDE and having Intellisense on them is fine, and I won't have any problem getting at them...but I can easily envision scenarios where I'm building them from scratch in code and manipulating them. That's how things evolved for me in VB and VBA. I used the designer created objects at first, then got comfortable creating and manipulating them in code. I don't know how things will evolve for me in .NET because the concept and the framework are so complex, unnecessarily so in my opinion. Microsoft led me to believe that for an experienced VB developer, jumping into .NET will be a "breeze!". It is not. It is excruciating. They seem to have hired people from all over the world to come in and try their damndest to muck up and complicate things as much as they possibly can. In that, they have succeeded. I submit the 5 or 6 data access objects and three languages one might use just to get back a stinking @EmployeeID - as evidence. It's as if .Net has a very thick foreign accent that only a few can understand, and that we all know isn't going to get any more understandable as time goes on.

     

    In short, it's a steep curve. Some days I feel like I'm near the apex.

     

    Anyway, off I go to fry my brain on this *** some more. Take it easy.

    Monday, February 4, 2008 8:48 PM
  • If Microsoft ever said that learning .NET would be a breeze, they were lying.  Learning .NET has been the most challenging transition I've undergone in a my 30 years as a developer.  The .NET framework is immense and complex, and there are still big pieces of it (reflection, for instance) that I have only a passing acquaintenance with. 

     

    The apparent complexity of the framework classes is in part due to the fact that they implement enormous amounts of functionality.  ADO's a good example.  The data objects in VB6 let programs insert, update, and delete rows in a database. 

     

    ADO is designed to support a really complex use case:  pull data from a server onto a client, edit the data, and send the changes back to the server.  The data set has to be serializable, so that it can be sent via HTTP.  It has to track the state of every row, so that the update process can determine which rows the user has modified, and what modifications were made.  It has to track the original, proposed, and modified versions of every column.  It has to be able to generate diffgrams, so that the client can send updates to the server without having to send back the entire data set.  On top of that, it has do to all of the things that you'd expect a database to do:  enforce data types, assign identity columns, enforce referential-integrity constraints, and so on.  And there has to be a straightforward way of persisting the data in SQL Server, SQL Server CE, MySQL, Oracle, Access, Pervasive SQL, and God knows what else.  Since multiple clients may be trying to update the same database concurrently, its database adapter has to be able to detect concurrency exceptions.  And so on.

     

    All of this seems like a lot to wade through if you're just trying to get the most recently assigned Employee ID out of your database.  It's not really the right tool for that job.  But nobody wants to just do that job.

     

    Anyway, I completely sympathize with your frustration.  It's a hell of a lot to get your head around.  But there really does come a day where it starts to make sense.  (For me, it was the day I suddenly got the TextWriter.)

     

    I usually advise VB6 programmers to learn C#.  Not just because I like C# more than I like VB.NET, but because its complete unfamiliarity doesn't mislead you into thinking it works in some way you understand, the way VB.NET does.

    Monday, February 4, 2008 9:30 PM
  •  

    Quote:

    "I usually advise VB6 programmers to learn C#.  Not just because I like C# more than I like VB.NET, but because its complete unfamiliarity doesn't mislead you into thinking it works in some way you understand, the way VB.NET does."

     

    What an interesting viewpoint. I've never heard anyone present the case for C# in this way. It does provoke some thought on the matter.

     

    But no worries...I've already discovered, and resigned myself to, the fact that VB.Net doesn't work in some way I understand. The core operators, functions, keywords and such are still there, sure. But I quickly realized that the .Net framework wasn't going to be a matter of printing 10 or 12 pages describing an object model and learning it by heart in a couple weeks. In short, my familiarity with VB isn't misleading me into thinking this will be easy, at least not now. Had I taken your advice from day one, perhaps I'd be farther along...I can't really know that now. I do think .Net development should have been presented as the radical sea change that it is, however.

     

    I was home sick today, so spent my time learning to configure and use the Enterprise Data Access Application Block. One step closer to the day it all starts to make sense.

     

    Which reminds me - one of the biggest hurdles I've encountered is that there is such a bewildering array of tools and technologies in the framework and in Visual Studio, it's extremely difficult to get started on a real project. One can't tell how in the world to architect the thing. There are lots of articles describing the pros and cons of particular scenarios. The authors attempt to lay it all out so the reader can decide which route to take...but there are so many routes that it's actually frustrating to read the articles.

     

    I'm getting there, though. I am *starting* to become a fan of Smart Clients. When I first dove into this and quickly got lost, I said,

     

    "I'm going dbdirect methods all the way, buddy...this is too confusing. I'm just on board to use the pretty new controls."

     

    But I began to see the benefits of disconnected DataSets, and I think I'm actually a convert now.

     

    I happen to believe also that the use of a best practices Data Access Layer is going to help me retain my sanity.

    Tuesday, February 5, 2008 7:48 AM