views:

217

answers:

2

Guys,

I'm writing a class to represent a row from a SQL query. I want the field data to be accessed via the indexer property of the class. This is straightforward enough if I load the data into an internal List of Object. I've already tried this and am not happy with the boxing for the primitives. Boxing increases the memory requirement by 20%. I would like to store the primitives as primitives in the class. The DataTable class stores primitives by creating arrays for each column in the schema returned from IDataReader. I implemented a class this way but I would prefer the data be stored with the row object rather than in a column that is referenced internally by the row.

Any ideas on accomplishing this?

+2  A: 

Only 20% overhead? You're lucky! I just cleaned up some code where it added a fourty-fold performance decrease (not counting the impact of the extra memory)! Anyway, the typical way to prevent using object is by starting using generics. Here's a simplified example:

class RowRepresenter<T>
{
    //....
    public T this[int index] {get; set;}  // implementation left out
}

// initialize, suppose the properties (indexers) should be ints:
RowRepresenter<int> myInstance = new RowRepresenter<int>();
myInstance.LoadData();

// get data (i.e., your indexer)
int somefield = myInstance[2];   // no overhead, no casting required
Abel
How does this handle multiple types in a single row?
Reed Copsey
You talked about indexers. You either have one type per indexer, or you don't. If you have multiple types per indexer, you cannot avoid using boxing, that's the price you pay for not using type-safety. Normally, you create a class that matches your data tables somewhat 1:1. The types then match the types in the DB. Using generics, you can remove some of the more tedious parts of using actions with these types, so you don't have to write the same get-from-db and store-to-db code again and again. This is a typical DAO scenario.
Abel
Sorry, the "you" applied to Reed, I thought it was Steve when I wrote the answer to the comment ;-)
Abel
@Abel - I'm not too worried about the boxing that occurs via a class indexer that takes a string fieldname and returns an object value. Perhaps I should be, but for now I'm focused on storing the row data internally as primitives instead of objects. Less memory overhead internally is the name of my game for today. I can write a tool to gererate a DAL but I'm looking for a class to take row data from any arbitrary query.
Steve
@Reed - I didnt catch the boxing from the generic class itself, you are correct. This would not save memory.
Steve
@Steve: If you're doing one of these per column, you're still boxing. If you create a struct or class to hold your entire row, that's specific to your type, then you can avoid it this way.
Reed Copsey
@Steve: You don't need to write a tool, there are already too many around, I'm sure there's one that fits your needs. I've seen dozens of DAO designs, and never needed objects to store data, but then I never require to *"take row data from an arbitrary query"*, I always try to make the mapping typed. Easier to understand, better performance, better memory requirements and simply way easier to program in the long run. That said, I'm glad you've found a way with dynamic type creation. A really hard path to take, but a fun one! NHibernate, for one, does the same internally.
Abel
+2  A: 

You can generate structure type to represent a row. It can be done dynamically and it is possible to do it so there will not be any boxing. I am not sure it is worthy the effort though

mfeingold
Why should it be a structure type and not a class?
Amnon
+1 That's a cool idea but as you say, I don't know that I'm ready to go there yet. I'll try the generic approach first and if it doesn't cut it, I'll try creating an internal structure dynamically. Thanks
Steve
@Reed - I didnt catch the boxing from the generic class itself, you are correct. This would not save memory.
Steve