Ok..
You're almost there:
now, your CollectionBase (your implementation), will need to add a .Sort
method.
the .Sort method takes an IComparer object. You create your own IComparer.
Here is a sample. Assuming you already have an object called Employee, with
2 properties
public int Age
public string Name
namespace MyApplication.BusinessLogicTier
public class EmployeeComparer : IComparer
{
private EmployeeComparerSortColumns m_sortValue;
public enum EmployeeComparerSortColumns
{
None = 0 , Age = 1 , Name = 2
}
public EmployeeComparer(EmployeeComparerSortColumns sortValue)
{
m_sortValue = sortValue;
}
public int Compare(object x,object y)
{
switch(m_sortValue)
{
case EmployeeComparerSortColumns.Name :
case EmployeeComparerSortColumns.None :
return
((MyApplication.BusinessLogicTierEmployee)x).Name.CompareTo(((MyApplication.BusinessLogicTierEmployee
)y).Name );
//break;
case EmployeeComparerSortColumns.Age :
return
((MyApplication.BusinessLogicTierEmployee)y).Age.CompareTo(((MyApplication.BusinessLogicTierEmployee)x).Age
);
// break;
default:
return
((MyApplication.BusinessLogicTierEmployee)x).Name.CompareTo(((MyApplication.BusinessLogicTierEmployee)y).Name
);
// break;
}
}
}
}
Ok, your CollectionBase object will have a .Sort method.
MyCollection.Sort (IComparer ic) // it may be "override", I'm going from
memory.
{
this.innerList.Sort(ic);
}
Notice you call the base class' Sort method.
Then you do something like
MyCollection my = new MyCollection();
my.Add ( new Employee() );
my.Add (new Employee() );
EmployeeComparer ec = new EmployeeComparer
(EmployeeComparer.EmployeeComparerSortColumns.Age);
my.Sort(ec);
I think those are the pieces.
The way I wrote the EmployeeComparer , means you don't have to write a
different one for each property, because you have an enum in the
constructor. A tad bit cleaner.
...
I am suggesting this route for 2 reasons:
Less overhead than the DataSet. Everybody likes to use/suggest datasets,
because they're quick. However, there isn't magic fairly dust, because they
do so much, they have alot of overhead with them.
Using the IDataReader ... and putting that into a CollectionBase, is alot
less overhead. (It may not seem that way, but populating a custom
CollectionBase is about 30% faster in my personal tests).
#2, you can cache a true CollectionBase (filled with MyObject's) alot better
than a DataSet.
Because of your large number of records, OVERHEAD is your biggest enemy.
I'm not even saying this way will definately work. I'm saying it has a lot
better chance that a DataSet.
After you get working, then you may want to add the
[Serializable]
attribute to your MyObject definition, and your MyCollection objects.
(it looks like this in C#
namespace MyApp
{
[Serializable]
public class MyObject
{
}
}
What you're doing here is more work, but you pay the price for less
overhead.
...
PS
You should also keep your ( IDataReader to MyCollection ) converter code
generic, in its own routine. Thus you can re use it.
Something like:
public MyCollection TransformTheIDataReaderToMyCollection (IDataReader idr)
{
MyCollection returnColl = new MyCollection();
while (idr.Read()) // my syntax might be a little off here, I'm going from
memory.
{
MyObject o =new MyObject();
if( !idr.IsDBNull( 0 ) )
{
o.Age = idr.GetInt32(0);
}
if( !idr.IsDBNull( 1 ) )
o.Name = idr.GetString(1);
}
returnColl.Add ( o );
}
return returnColl;
}
This way.... you can populate your IDataReader with
All Records (no filter)
Some records ( filters applied , like "Age = 34" in your Select query)
1 record ( Where Emp.EmpId = 12345 )
...
Ok.... I think that should help.
You're writing some more advanced code than just populating a DataSet.
As you become more famaliar with CollectionBase , it may turn into your
bread and butter for object storing.
Especially with the generic TransformTheIDataReaderToMyCollection method.
One last thing:
Where I have:
if( !idr.IsDBNull( 0 ) )
{
o.Age = idr.GetInt32(0);
}
You probably want to put in a CONST or some kind of enum or structure for
"0", to make the code more readable.
private readonly int CONST_AGE_COLUMN_ORDINAL_POS = 0;
if( !idr.IsDBNull( CONST_AGE_COLUMN_ORDINAL_POS ) )
{
o.Age = idr.GetInt32(CONST_AGE_COLUMN_ORDINAL_POS ) ;
}
You check out some other hints at my blog at:
http://spaces.msn.com/sholliday/
As the other guy suggest, implementing Paging ( Page1 , Page2 ,..... PageN)
might be something to look at.
While he suggests caching the DataSet object, I would still promote the
MyCollection idea.
If you want to find a cool web caching mechanism, check out my 10/24/2005
entry on my blog.
...