Internal Class Storage as DataRow

  • Thread starter Thread starter Eric Barr
  • Start date Start date
E

Eric Barr

Hi all,

I have a data intensive application and I'm in the process of design a
middle tier object to abstract the data model. All the properties of these
objects are going to need private internal storage. Each property maps
directly to a database field.Since the object is so data intensive i am
going to use the SQL data types for a cleaner mapping to my DB layer.


I was thinking of using the DataRow object as my internal storage mechanism.
It would provide a nice layer type checking for my data. Is this even a
viable option ?

Any feed back or thoughs would be appreciated.

Regards.
-eric
 
This may be viable, but if speed is of concern, then it may not be the
quickest way to move data in and out. Honestly, I don't know what the
overhead is of accessing data in a DataRow. The underlying mechanism may be
quite optimal, but my guess is that it's going to cost you more in terms of
performance than simply storing the data in a structure or structure-like
class with properties.

Pete
 
My problem with using DataRows for that kind of application (along with
quite a few other .net classes) is that there doesn't appear to be any
*practical* method of subclassing them.

You can only construct them through the DataTable.NewRow method which you
can't get at. You can kind-of subclass the DataColumns and DataTable though
and get a bit of extra behaviour that way.

But then there is no way that I can see of copying eg subclassed DataTables.
I can't see any way of writing a function like MyDataTableSubClass.Clone().
(because you can't make use of DataTable.Clone() in it). What would be
useful is a function that did almost the same thing as Clone;
DataTable.Copy(ref DataTable). Then the subclassed Clone and Copy would call
the base Copy. Maybe I'll start a new thread asking how people deal with
that kind of issue...

Tom
 
Tom,
Have you looked at the code Typed DataSet creates?

To have DataTable.NewRow return your sub-typed DataRow, you need to override
the DataTable.NewRowFromBuilder method.

For details see:

http://msdn.microsoft.com/library/d...mdatadatatableclassnewrowfrombuildertopic.asp

Also check out the code created from creating a Typed DataSet in VS.NET!

David Sceppa's book "Microsoft ADO.NET - Core Reference" from MS Press has a
section that discusses the "magic" behind the DataSet object model. I find
his book to be a very good tutorial on learning ADO.NET as well as a good
desk reference once your using ADO.NET.

Hope this helps
Jay
 
Thanks for that. Subclassing from DataRow is achievable as you say.

I just happened to be not interested in typed datasets at all. That isn't
why I want to subclass the data classes so I didn't look at that particular
chapter in Sceppa (which is my ADO bible) very closely. What I found in the
generated sample was the

internal MytableRow(DataRowBuilder rb) : base(rb)
{
this.tableMyTable = ((MyTableDataTable)(this.Table));
}

code which uses DataRowBuilder to achieve something. (an explanation which
is not in the DataRow constructor documentation or the DataRowBuilder
documentation URL that you gave me)

The DataSetDerivative.Clone() code was interesting too

public override DataSet Clone()
{
MySet cln = ((MySet)(base.Clone()));// I don't understand this line
cln.InitVars();
return cln;
}

What I don't understand here is how casting a DataSet to a MySet can work?
If you cast to a derived class does it construct a copy with the derived
members at default values?

Thanks again.

Tom
 
Tom,
I just happened to be not interested in typed datasets at all.
However! What I am suggesting is the code the typed datasets generates is
the means to "your" end! :-)
internal MytableRow(DataRowBuilder rb) : base(rb)
{
this.tableMyTable = ((MyTableDataTable)(this.Table));
}
This is a constructor that creates a new derived DataRow based on a
DataRowBuilder, DataRowBuilder is an implementation detail that I haven't
concerned myself with (I use it where its "required" in the DataSet OM). The
constructor is internal, as its an implementation detail of the class
library, it helps enforce the "you cannot be create DataRows without using
the DataTable.NewRow method" "contract" of the DataTable. Its only part of
the picture, IMHO the important part of the"magic" is
DataTable.NewRowFromBuilder. I'm sure DataRowBuilder is simply a Parameter
Object (http://www.refactoring.com) to pass needed information from the base
DataTable to the base DataRow during construction.

In your original post, I was under the impression you did not follow how to
get a derived DataRow to work, you "get it to work" by implementing the
NewRowFromBuilder function in a derived DataTable. The NewRowFromBuilder is
a Template Method Pattern that is used in the implementation of a
DataTable.NewRow, implementing this function enables a derived DataTable to
return type specific DataRows... The non-overridable DataTable.NewRow calls
the overridable DataTable.NewRowFromBuilder to get a type specific object
during the creation of a New DataRow, its the "out" that is required to get
a type specific row, NewRowFromBuilder also happens to be a Factory Method
(as it returns a new row).
What I don't understand here is how casting a DataSet to a MySet can work?
If you cast to a derived class does it construct a copy with the derived
members at default values?
Looking at the code of the Typed DataSet, immediately after the Clone method
there is a CreateInstance method that does return a new typed DataTable.
Seeing as the NewRow used a Template Method (NewRowFromBuilder) it does not
surprise me that it appears Clone uses a Template Method (CreateInstance). I
don't see this specifically documented! However! by putting break points in
the code, you can see when Clone is called CreateInstance is also called. If
you remove the DebuggerStepTrough attribute in the typed dataset code its
easier to single step the code...
If you cast to a derived class does it construct a copy with the derived
members at default values?
Fortunately .NET does not have this feature, you need to explicitly create
objects of the type you want, or within YOUR code implicitly use conversion
operators (which explicitly create objects). Which is where the various
Factory Method patterns are useful, especially when coupled with a Template
Method pattern. A method in a class library can define a factory/template
method that is used by derived classes to create a type specific derived
objects.

Again IMHO studying how the Typed DataSet is generated lends itself very
well how to implement derived DataTables yourself. Remember a Typed DataSet
is simply classes that are derived from DataSet, DataTable, DataRow along
with EventArgs... Seeing how the designers leverage the DataSet OM, should
help you leverage the DataSet OM...

For details on Template Method Patterns & Factory Method Patterns, I would
refer you to "Design Patterns - Elements of Reusable Object-Oriented
Software" by the GOF
(Gang of Four) Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides from
Addison Wesley Professional Computing Series

Hope this helps
Jay
 
Jay B. Harlow said:
Tom,
However! What I am suggesting is the code the typed datasets generates is
the means to "your" end! :-)
Yes, I know, it looks really helpful to show the techniques even though the
specifics are not what I want. I was just explaining why I hadn't picked up
on it without your help! I didn't want to appear as stupid as my original
post had suggested I was.
This is a constructor that creates a new derived DataRow based on a
DataRowBuilder, DataRowBuilder is an implementation detail that I haven't
concerned myself with (I use it where its "required" in the DataSet OM). The
constructor is internal, as its an implementation detail of the class
library, it helps enforce the "you cannot be create DataRows without using
the DataTable.NewRow method" "contract" of the DataTable. Its only part of
the picture, IMHO the important part of the"magic" is
DataTable.NewRowFromBuilder. I'm sure DataRowBuilder is simply a Parameter
Object (http://www.refactoring.com) to pass needed information from the base
DataTable to the base DataRow during construction.

In your original post, I was under the impression you did not follow how to
get a derived DataRow to work, you "get it to work" by implementing the
NewRowFromBuilder function in a derived DataTable. The NewRowFromBuilder is
a Template Method Pattern that is used in the implementation of a
DataTable.NewRow, implementing this function enables a derived DataTable to
return type specific DataRows... The non-overridable DataTable.NewRow calls
the overridable DataTable.NewRowFromBuilder to get a type specific object
during the creation of a New DataRow, its the "out" that is required to get
a type specific row, NewRowFromBuilder also happens to be a Factory Method
(as it returns a new row).
Yes, I understood this already once you directed me at the sample example of
typed datasets from Sceppa.
Looking at the code of the Typed DataSet, immediately after the Clone method
there is a CreateInstance method that does return a new typed DataTable.
Seeing as the NewRow used a Template Method (NewRowFromBuilder) it does not
surprise me that it appears Clone uses a Template Method (CreateInstance). I
don't see this specifically documented! However! by putting break points in
the code, you can see when Clone is called CreateInstance is also called. If
you remove the DebuggerStepTrough attribute in the typed dataset code its
easier to single step the code...
I understand this now it has been pointed out to me that Clone returns a
copy of the current derivation from DataTable, not a base DataTable. The
documentation is clear on this point but I think my C++ experience led me to
the oversight of something that would be impossible in C++.
Fortunately .NET does not have this feature, you need to explicitly create
objects of the type you want, or within YOUR code implicitly use conversion
operators (which explicitly create objects). Which is where the various
Factory Method patterns are useful, especially when coupled with a Template
Method pattern. A method in a class library can define a factory/template
method that is used by derived classes to create a type specific derived
objects.
I realise it doesn't have this feature now. I didn't want it; I was trying
to understand the code. I was baffled by the how cast of Clone was working,
not realising that Clone was already returning the correct type and it just
needed casting. Now I understand.
Again IMHO studying how the Typed DataSet is generated lends itself very
well how to implement derived DataTables yourself. Remember a Typed DataSet
is simply classes that are derived from DataSet, DataTable, DataRow along
with EventArgs... Seeing how the designers leverage the DataSet OM, should
help you leverage the DataSet OM...
Yes it looks very helpful. I already had derivations of DataSet and
DataTable but I couldn't see how to derive DataRow. I do now. I also
couldn't understand how to Clone derived sets and tables (which luckily I
didn't need to do yet) but I can now I know that Clone clones the derived
class.Thanks again. You have been really helpful.

Tom
 
In my specific application subclassing the data row isn't really a
requirement. I am more concerned with a the choice of internal storage
mechanism. It seems very logical to use data rows to hold a collection of
fields in a Data Access Layer component. Using data rows seems like it
would provide a tight mapping to the database. It seems convenient. If
defined properly it would provide a nice layer of validation.

I haven't found an articles that describe using data rows as a storage
strategy. I can't even find anecdotal evidence using google groups. Just
seems like others would have had this dicussion.

Regards,
-eric
 
Eric,
I haven't found an articles that describe using data rows as a storage
strategy. I can't even find anecdotal evidence using google groups. Just
seems like others would have had this dicussion.

Are you considering using DataRows outside of the DataTable structure or
using a DataTable itself? Remember that you "cannot" use a DataRow without
having a DataTable to create it, if you have a DataTable to create it, I
would go ahead and use the DataTable to manage it.

Sceppa's book previously mentioned has lots of thoughts on using DataTables
& DataSets, as does MSDN. One alternative to the DataSet OM is Rockford
Lhotka's CSLA.NET http://www.lhotka.net/.

Martin Fowler offers some other alternatives in his book "Patterns of
Enterprise Application Architecture" from Addison Wesley.

Note Martin Fowler also has some thoughts on using an Array of Objects
(which is what DataRow seems to me to be) in his book "Refactoring -
Improving the Design of Existing Code" also from Addison Wesley. See the
"Replace Array with Object" refactoring
http://www.refactoring.com/catalog/replaceArrayWithObject.html

Hope this helps
Jay
 
Tom,
Yes, I know, it looks really helpful to show the techniques even though the
specifics are not what I want. I was just explaining why I hadn't picked up
on it without your help! I didn't want to appear as stupid as my original
post had suggested I was.
I rarely if ever assume a poster is "stupid"!

I may assume the poster, me included, may be looking to the left, when the
solution is starting at them on the right, so I try to offer alternatives.

Jay
 
Jay B. Harlow said:
Tom,
I rarely if ever assume a poster is "stupid"!

I may assume the poster, me included, may be looking to the left, when the
solution is starting at them on the right, so I try to offer alternatives.

Jay
The only stupidity I try to assume before posting is my own. But on this
occasion I failed to realise the extent of my idiocy! When I first believed
(incorrectly, months ago) that Clone didn't do what I wanted I should have
asked the question immediately, because in retrospect it was inconceivable
that the designers of such a fine system would have made such an elementary
error as not permitting programmers to copy instances of sub-classes. By
believing that they would make such an error I was setting myself up as
cleverer than them; not a good move.

This conversation has taught me (again) how vast a subject .NET is. I've
been writing C# code for months now without truly understanding the
implications of class metadata being available in code. C# is superficially
similar to C++ but in reality the differences in required approach and
technique to achieve the best results are enormous. The danger/delight of
..NET is that getting trivial programs that accomplish quite a lot to work is
really easy, regardless of your previous experience. But the underlying
environment is *so* different despite the superficial similarity that
writing "proper" programs has quite a learning curve.

I think I probably need to go away and reread several chapters of "applied
ms.net framework programming" (Richter) or something similar now that I have
real-world experience of what it is talking about to hang the explanations
on.

Tom
 
Now this is useful information for me. The inability to create a datarow
without a data table defenitely impacts my decision. Thanks Jay.

DataTable will have to be the lowest unit of storage i use in my object.
The more i look at ADO.NET the more it makes me smile. Between the data
table /set/ and row they support quite of few of the features i would have
needed to implement by hand. It supports :
- the Original and Current versions of the row
- null values
- Clone and Copy functions
- abitlity to merge
- fromXML and toXML style functions

I am still going to be cautous about the weight / footprint incurred by
using datatables, but at this point the benefits seem to outweight the
drawbacks. I'll just have to keep an eye on it.

Regards,
-eric
 
Back
Top