Determining the TableAdapter (for a given typed DataTable) needed at runtime

cjard

Well-known member
Joined
Apr 25, 2006
Messages
7,081
Programming Experience
10+
Hi All

Suppose I have 17 different typed datatables, and they will all be updated by a single datagrid at some point (at different times) in order to update the database, I nee dto use one of the 17 typed tableadapters that pair with the datatables..

Now, my question is, can this be done programmatically?

Can i say something like:
VB.NET:
Dim ta as TableAdapter
ta = DirectCast(myDataGrid.DataSource, DataTable).GetRelevantTableAdapter()



I currentlky know of no way to do this, other than my current plan:
I create a tableadapter for each table at startup, just so i can fill the datatable with values. If I retain this in a hashtable or colelction keyed by the datatable name, then i can look it up like:

VB.NET:
Dim ta as TableAdapter
ta = MyHashtable( DirectCast(myDataGrid.DataSource, DataTable).Name )


AFAIK there is no direct link between datatables and their tableadapters, but if anyone knows if there is and how i can use it to retrieve the relevant table adapter for a given datatable, i'd love to know.
Thanks




**update:
I cant think of an easy way to do this - not by overloaded methods, nor hashtable storage - i cant treat a table adapter with sufficient genericity and all because there isnt a common base class for tableadapters that defines the ability to call an Update method. Am i going to have to write my own base and then when i do this, how to i write my method Update, so that the implementations in ym dataset override this method correctly? If they arent declared as override, i dont think i can slip into the hierarchy in the middle! :(
*thud*
 
Last edited by a moderator:
Possible Solution

Hi cjard,
there is only one way I can think of to do this and that is a mult-state form. These are elegent little beasts that I have used from time to time. Essentially it works like this. Have a new constructor that defines each adapter type that the form containing your datagrid will load and save info from. When you are editing a given table create an instance of this form with the appropriate constructor. In the constructor set a member variable to a value from an enumeration that lists each adapter type. When you call an update method,the method will use a case statement to determine which update code to call. Of course, your constructors will be the methods that will load the data into the datagrid as well. Since each constructor will have a different datatype the overload will work fine as well.
Let me know if this works.
Cheers.
 
That sounds like it works a treat if one is creating a new form instance for each datatable.... but what about the case where the same form is being reused? Say I have a form with three buttons and one grid... I click button 1 and I get Customers. I click button 2 and I get Companies, I click on Button 3 and I get orders.... each time the grid is cleared out and re-loaded with the new data..... ????

-tg
 
Then you will get it to work via maintaining STATE of your form Every time you click a new button set the user created m_STATE variable to the state that the datagrid is in. When you click update, detect the m_State Variable in a case statement and then all the appropriate code. This is not as elegent since it is prone to change with each button push.... hence it may not be as stable as the method I outlined.

Of course, nothing prevents you from creating the app as MDI, putting all the buttons for customers, companies and such in that and then constructing the same for multiple times. the best practice programming guidline is to make one form do one task and do it well. If you have one form editing customers and the same form editing companies you violate this best-practice.

Cheers.
 
Mmmh.. the inference was not to use a case statement at all, but (without using reflection) for a given datatable Customers, get an instance of the Customers TableAdapter in order for it to be updated.

I went oto ask a related question this morning and its funny that this thread should be notified in my inbox now. The way I would propose to do it is (even though i have used a case statement ugh):

Declare a new class called something relevant. For example if all my tables i want to update are lookup tables i'll call it GenericLookupTableTableAdapter:

VB.NET:
Public MustInherit Class GenericLookupTableAdapter
  Public MustOverride Sub StandardUpdate(dt as DataTable)
End Class

In the designer, set all lookup table TableAdapters to inherit from this

View the code of the data set designer

Add code in this pattern to the end of the designer.. AFTER the End Class line for the dataset itself. (in this code my dataset is called GhostDS)

VB.NET:
Partial Class GhostDS
End Class  'after this line!!!!!
 
 
'i;; put this in here because when i wanna see a tableadapter i look in the
'designer.. its logical that extra table adapter code should go in this file
Namespace GhostDSTableAdapters
 
    'all tableadapters are declared by the designer as partial
    'so we dont have to edit auto genned code to change them
    Partial Class SomeLookupTableTableAdapter
        Public Overrides Sub StandardUpdate(ByVal toUpd As DataTable)
            If TypeOf toUpd Is GhostDS.SomeLookupTableDataTable Then
                Me.Update(DirectCast(toFill, GhostDS.SomeLookupTableDataTable), clientRef, forDate)
            Else
                Throw New StrongTypingException("SomeLookupTableTableAdapter.StandardUpdate() requires that a " & _ 
                                                                 "DataTable of type SomeLookupTableDataTable be passed to it")
            End If
        End Sub
    End Class
End Namespace

You can now declare a Dictionary(Of GenericLookupTableAdapter) and store in it, (keyed with the datatable name for example) an instance of each tableadapter because they now inherit from a parent that has something TableAdaptery about it
 
Back
Top