Polymorphic object fetching with code gen

Polymorphic object fetching with code gen

Old forum URL: forums.lhotka.net/forums/t/816.aspx


skagen00 posted on Friday, August 04, 2006

I am loading a collection of varying types.

My collection isn't code generated, but I want to keep its contained objects code generated as those will have varying properties.

Here's my approach right now.

My fetch in the collection looks like this:

private void Fetch(SafeDataReader dr)

{

   RaiseListChangedEvents = false;

   while (dr.Read())

         this.Add(ProfileRoleFactory.GetProfileRole(dr));

   RaiseListChangedEvents = true;

}

ProfileRoleFactory instantiates the proper object as such:

internal static IProfileRole GetProfileRole(SafeDataReader dr)

{

   IProfileRole fetchedRole;

   switch (dr.GetGuid("ProfileRoleType"))

   {

      case ProfileRoleType.GranteeRole:

         fetchedRole = (IProfileRole)ProfileRoleGrantee.GetProfileRoleGrantee(dr);

         break;

      case ProfileRoleType.VendorRole:

         fetchedRole = (IProfileRole)ProfileRoleVendor.GetProfileRoleVendor(dr);

         break;

      case ProfileRoleType.StandardRole:

         fetchedRole = (IProfileRole)ProfileRoleStandard.GetProfileRoleStandard(dr);

         break;

      default:

         fetchedRole = null; // Throw exception.

         break;

      }

   return fetchedRole;

}

Now under this scenario, I would need to do a wide selection in my stored procedure, essentially joining my main profilerole table with all of the "custom" types (there will probably be about 5), selecting all columns. The factory method of each of my types would be selecting from the datareader the values that they need.

My worry here is about performance. A profile has profile roles, typically no more than three, but each select (since it is so wide) might have about 100 columns (of which each profile role might use 20 or so).

Perhaps with only three rows (and 80% of the values in each row being null) shouldn't be a concern. Is there a better means? (Keep in mind I'm using code generation, so my fetches are generated and waiting for me - the challenge is just getting the appropriate datareader passed to the factory methods of each type of profilerole).

 

skagen00 replied on Friday, August 04, 2006

I have thought of one option, and that's to have a separate select for each of the robust system ProfileRoles.

SELECT ProfileRole.SystemId, ProfileRole.IsActive, ProfileRoleGrantee.* (brevity)

FROM ProfileRole, ProfileRoleGrantee WHERE ...get profile's grantee role...

SELECT ProfileRole.SystemId, ProfileRole.IsActive, ProfileRoleVendor.* (brevity)

FROM ProfileRole, ProfileRoleVendor WHERE ...get profile's vendor role...

SELECT ProfileRole.SystemId, ProfileRole.IsActive

FROM ProfileRole WHERE ...get profile's other profileroles (standard)...

In my collection's fetch, I would handle each of the "special types" first. (There will likely grow to be about 5 or 6 of these over the course of the system's development).

private void Fetch(SafeDataReader dr)

{

   RaiseListChangedEvents = false;

   while (dr.Read()) // Grantee Result Set

      this.Add(ProfileRoleFactory.GetProfileRole(dr)); // Could bypass the factory I guess.

   dr.NextResult();

   while (dr.Read()) // Vendor Result Set

      this.Add(ProfileRoleFactory.GetProfileRole(dr)); // Could bypass the factory I guess.

   dr.NextResult();

   while (dr.Read()) // Standard (Other Roles) Result Set

      this.Add(ProfileRoleFactory.GetProfileRole(dr)); // Could bypass the factory I guess.

   RaiseListChangedEvents = true;

}

This would introduce one additional place where I am "adding a case for each type" but with the limited number of cases long term (5-6) it seems like this would be a nice way to handle the performance issue. Thoughts?

Thanks!

 

Copyright (c) Marimer LLC