Plip's Weblog

Phil Winstanley - British Microsoft ASP.NET MVP & ASP Insider.

Part 3: Using Strongly Typed Objects and Collections to replace DataSet’s in your .NET applications.

Populating objects and collection from Databases

The function of populating your objects is relatively simple, all you basically need to do is retrieve the Data from it’s store and pass it in to your objects.

The best way of achieving this is by having all of your Data Access code in one place, then using that code throughout your applications. The Data access code can be project specific or more general and this will depend on your needs.

An example of this follows: -

 

public FooCollection PoshFoos()

{

          //Setup some Variables

          string ConnectionString = ("MySqlServer");

          string StoredProcedure = ("MyStoredProc");

          FooCollection CC = new FooCollection();

          //Set up the Parameters for the Database Code

          NameValueCollection Params = new NameValueCollection();

          Params.Add("@FoosExistInOtherTable","FooDatabase.dbo.PoshFoos");

          //Retreive the Data using our custom call (DAL)

          DataSet Foos = DataAccess.Out.GetDataSet(ConnectionString,StoredProcedure,Params);

          //Loop through the rows collected and populate the Foo Object

          foreach(DataRow DR in Foos.Tables[0].Rows)

          {

                   Foo C = new Foo();

                  

                   C.Id = Convert.ToInt32(DR["FooId"].ToString());

                   C.Title = DR["Title"].ToString();

                   C.ExteriorColor = DR["ExteriorColour"].ToString();

                   C.InteriorColor = DR["InteriorColour"].ToString();

                   C.InteriorMaterial = DR["InteriorMaterial"].ToString();

                   C.Price = Convert.ToDouble(DR["Price"].ToString());

                   C.Miles = Convert.ToInt32(DR["Miles"].ToString());

                   C.Registration =  DR["Registration"].ToString();

                   C.Transmission = new Transmission(DR["TransmissionCode"].ToString(),DR["TransmissionName"].ToString());

                   C.Fuel = new Fuel(DR["FuelCode"].ToString(),DR["FuelName"].ToString());

                   C.Manufacturer = new Manufacturer(Convert.ToInt32(DR["ManufacturerId"].ToString()),DR["ManufacturerName"].ToString());

                   C.Model = new Model(Convert.ToInt32(DR["ModelId"].ToString()),DR["ModelName"].ToString());

                   C.Derivative = new Derivative(Convert.ToInt32(DR["DerivativeId"].ToString()),DR["DerivativeName"].ToString());

                   C.Description = DR["Description"].ToString();

                   C.HoldingCenter = new Center(Convert.ToInt32(DR["CenterId"].ToString()),DR["CenterName"].ToString());

                   CC.Add(C);

          }

          //Return the Foo object

          return CC;

}

 

Sometimes you will even want to encapsulate the above and add application logic such as Caching, and example of which follows: -

 

public BusinessObjects.FooCollection All()

{

          FooCollection CC = new FooCollection();

         

          if (System.Web.HttpContext.Current.Cache["PoshFoos_" + _Results.ToString()] != null)

          {

                   CC = ((FooCollection)System.Web.HttpContext.Current.Cache["PoshFoos_" + _Results.ToString()]);

          }

          else

          {

                   ReturnFoos RC = new ReturnFoos();

                   RC.NumberOfRowsToReturn = _Results;

                   CC = RC.PoshFoos();

System.Web.HttpContext.Current.Cache.Add("PoshFoos_" + _Results.ToString(),

CC,

null,

DateTime.Now.AddMinutes(Convert.ToInt32(60),

System.TimeSpan.Zero,

System.Web.Caching.CacheItemPriority.Normal,null);

          }

         

          return CC;

}

 

Another way, sometimes the best for persuading others to adopt this technique is by having methods on your objects that perform the data access, an example of which follows.

 

Foo.Select(123456);

Foo.Update();

Foo.Delete();

Whilst this moves away from a disconnected architecture it allows developers to get away without having to perform any manual Data Access.

It’s best to place all Data Access code that is used inside your objects in a separate Data Access class of some sort, this way you do not have to clutter your objects with a lot of methods to retrieve data, but instead instantiate your Data Access class, give it the Object you want Filling, and pass it the Criteria against which you wish the SQL Queries to be run. This is Similar to the way DataAdapter’s are currently used. 

There is no “right” was to populate your objects, all have their pitfalls.

Posted: Apr 11 2004, 09:16 AM by Plip | with 19 comment(s)
Filed under:

Comments

Andres Aguiar said:

Doing it this way you have the worst of both worlds.

You should load it from a DataReader and not a DataSet.
# April 11, 2004 9:30 PM

Phil Winstanley said:

Andres,

Thanks for that, and of corse you are right, although this method allows for the easier transition for people only using DataSet's at the moment, which from my experience tends to be the majority of developers. Datareaders are of corse much faster.
# April 12, 2004 9:24 AM

Barry Gervin said:

So how do you update the database? How do you handle optimistic concurrency? I don't see you storing the original values of any columns?
# April 13, 2004 3:06 PM

Phil Winstanley said:

Barry,

Good question! I don't update the DataBase. :)

These objects are explicitly used to represent read only Data on our front end web sites. We http://www.portfolio-europe.com develop web sites for about 30 Vehicle manufacturers around the world and we are always recreating very similar code, these objects have been great for me to standardise the Code used on the Web Sites so that when you're binding data to a page, it's always a Car or a CarCollection.

For creating objects to Update the DataBase you can read up on this book, it's what started me off on the strongly typed path: -http://tinyurl.com/2ff9w
# April 14, 2004 4:10 AM

Karl said:

pardon my possible ignorance...but is there a reason you are ToString()'ing then doing a Convert.Toxxxx ala:

Convert.ToInt32(DR["Miles"].ToString());

I thought it might be a clever way to handle nulls, but from what I can tell, ToString on DBNull returns "" which can't be turned to an int.
# April 14, 2004 8:48 AM

Phil Winstanley said:

No good reason :) Force of habit I think.
# April 14, 2004 9:22 AM

Karl said:

Any good way to handle null then? Or stick with the

if (DR["Miles"] == DBNull.Value){
C.Miles = 0; //some default value
}else{
C.Miles = Convert.ToInt32(DR["Miles"]);
}

of course, the default value could be assigned to the private field miles which would be even better.

You'd have the same null problem if you were using a DataSet..but it seems to me one of the advantages to the typed object approach is the ability to hide such ugliness.
# April 14, 2004 9:31 AM

Barry Gervin said:

You don't have the same problem with Datasets. DS's handle nulls so you don't have to do what you suggest. DefaultValue's and null's don't mean the same thing. If I don't know somebody's birthday - setting it to Jan 1, 1980 or some default value is going to insult or compliment somebody. If an ATM machine couldn't get my balance from my bank - I'd prefer it printed on my receipt that it didn't know my balance as opposed to putting in zero or -1 or something else - of course I wouldn't be opposed to int.maxvalue for that.

Untyped DS Access offers you IsNull(column) overloads on the datarow. Typed DS's also add Is<columnName>Null methods for you on the datarow for each nullible column which is nice.

The underlying implementation of this is nice and I'd suggest anyone looking into building their own custom entities exam the ds implementation - which uses a bit array for each column. The column value getter's always check the bit array which is fairly fast before looking at the underlying value array for the column.
# April 14, 2004 10:56 AM

Chris Frazier said:

Ever tried working with null values in a Typed or Untyped dataset? It sucks. Put simply - value types cannot be null.

The only way for you to get around the "null problem" is to either use specialized DBtypes that handle this, such as SqlDbTypes, use nullabletypes found on sourceforge, or use a rediculous representation (like double.MaxValue) that could not be represented realistically by the entity you are trying to represent.
# April 14, 2004 5:03 PM

Andrew Watson said:

Personally, I prefer to use a DataReader and pass it to the constricutor of the object (which then instantiates itself)... The data values all have a default, then you loop trough the columns skipping nulls and  matching the names to the variables you have created (switch case)

- it means the knowledge of the data structure is encapsulated in the representation

- it doesn't care if a column is missing in the data or not

Of course it still has a problem of representing nulls, but I figure that in most cases, null can be interpreted as something else for the presentation layer... I mean blank string, null, is there really much difference... id column is null or 0 do you really want to use 0 as an id anyway?  And again, at least that knowledge is encapsulated in one class... just a thought.

# September 5, 2007 10:30 PM

Mary-bb said:

<a href= http://fasster.angelfire.com >baltimore and convention center and headquarters</a> <a href= http://gertui.angelfire.com >nasdaq 100 tennis tournament</a>

# November 28, 2008 7:32 AM

Mary-di said:

<a href= http://fairra.angelfire.com >landls end</a> <a href= http://vonucshka.angelfire.com >chancellor internal med</a>

# November 28, 2008 2:38 PM

Mary-ib said:

<a href= http://chkola.angelfire.com >avlastkey</a> <a href= http://bustersw.angelfire.com >how to start a strawberry patch in alabama</a>

# November 28, 2008 7:42 PM

Mary-yk said:

<a href= http://kustur.angelfire.com >dad vail regatta</a> <a href= http://trututa.angelfire.com >ratings apartments eagle ridge alabama</a>

# November 29, 2008 12:39 AM

Mary-cb said:

<a href= membres.lycos.fr/dertull >zx10r graphics</a>

# December 26, 2008 5:24 AM

Mary-nw said:

<a href= http://adultromancefinder.com >find partner</a>

# February 28, 2009 10:31 PM

Mary-nw said:

<a href= http://adultromancefinder.com >find partner</a>

# February 28, 2009 10:31 PM

gas powered scooters said:

You will see extremely cheap gas powered scooters

www.world66.com/.../gas_powered_scoote

# June 10, 2009 7:04 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)