I have a data tier select method that returns a datatable. It's called from a business tier method that should then return a strongly typed generic List.
What I want to do is very similar (but not the same as) this question:
How do you convert a DataTable into a generic list?
What's different is that I want the list to contain strongly-typed objects rather than datarows (also, I don't have linq avaiable here yet).
I'm concerned about performance. The business tier method will in turn be called from the presentation tier, and the results will be iterated for display to the user. It seems very wasteful to add an extra iteration at the business tier, only do it again right away for the presentation, so I want this to be as quick as possible.
This is a common task, so I'm really looking for a good pattern that can be repeated over and over.
You will need to iterate through the datarows and convert them into your objects at some time anyway, but you could write a custom collection with a constructor that takes a collection of datarows and that converts each item into your object type when requested instead of all at once.
Say you define your custom collection that implements
IList<T>
. It could then have two internal fields - a reference to the collection of datarows and aList<T>
. TheList<T>
would be initialized to the length of the collection of datarows but with null values.Now in the indexer you could check if the
List<T>
contains a value at that index and if not you could create the object using whatever means would be useful and store it there before returning it.This would postpone the creation of your objects until they were requested and you would only create the objects that were requested.
Your objects would probably need a constructor taking a DataRow or you would need some sort of factory to create them, but that is another topic.
Do you know the structure of the
DataTable
and the typed object ahead of time? You could use a delegate to do the mapping. If you don't (i.e. all you know is aType
and properties) there are ways of accelerating dynamic member access (such asHyperDescriptor
).Either way, consider an iterator block; that way you don't have to buffer the objects an entire second time; of course, if you are only dealing with smallish rowcounts this isn't an issue.
Can you clarify any of those points? I can add a lot more detail...
At the simplest, what is wrong with:
(the problems in the above might steer the right approach...)
Just to provide some more user - friendliness to Mark's answer in a simple console app :
The problem with the sample above is that it is terribly slow. I have a DataTable with about 400 rows and this conversion takes a good 5 or 6 seconds!
It does seem like a pretty common task, so I'm surprised to not see someone here with a more performant solution.
* Update!! * Just for kicks, I thought I would try converting using LINQ instead of iterating through the DataTable and adding to my List. The following is what I did:
The first method (iterating through each row) took 5.3 seconds and the method using LINQ took 1.8 seconds!