locked
Data Access - Populating Business Objects RRS feed

  • Question

  • User102582072 posted

    I've always had a hard time trying to solve this issue.

    Has anyone got an elegant way in populating Business Objects?

    I have created generic mapping classes which populate objects based on the datareader, but I've always wondered how other people would handle this.


    Lets use an example.

    I have 2 business objects. "Person" and "Address". A person can have several address's 

    So i would do something like this

    public class Person
        {
            private int id;
            public int ID
            {
                get
                {
                    return id;
                }
                set
                {
                    id = value;
                }
            }
            private string firstName;
            public string FirstName
            {
                get
                {
                    return firstName;
                }
                set
                {
                    firstName = value;
                }
            }
            public List<Address> AddressCollection
            {
                get;
                set;
            }
    
            public Person()
            {
                this.AddressCollection = new List<Address>();
            }
        }
    
    
        public class Address
        {
            private string street;
            public string Street
            {
                get
                {
                    return street;
                }
                set
                {
                    street = value;
                }
            }
    
            public Address()
            { 
            }
        }


    If the result set is

    PersonID                     FirstName                            AddressID                     Address

    1                            Joe                                 1                               Example A

    1                            Joe                                 2                               Example B  

    2                            Bob                                 3                               Example C  

    3                            Kim                                 4                               Example D  


    whats the best way to populate a collection of person? 

    Originally what i was doing was checking the primary key and if it changed then i would then create a new object.

    I would so something like this in the PersonDAL


    public static List<Person> GetAllPersonList()
    
    
    {
    
    // Database call
    
    int tmp = 0;
    Person person = null;
    Address address = null;
    
    while (dr.Read())
    
    { 
        if(Convert.ToInt32(dr["PersonID"].ToString()) != tmp)
        {
            person = Fill.FillObject<Person>(dr);
    
        }
        address = Fill.FillObject<Address>(dr);
        person.AddressCollection.Add(address);
        tmp = Convert.ToInt32(dr["PersonID"].ToString());
    
    }
    }




    The FillObject method basically uses Custom Attributes, System.Reflection & Generics to create, populate and return the object. 


    Anyways the above concept works but i was wondering how other people handle populating a business object collection within a series of business objects?

    Any links to other websites or books so i can further my knowledge on this would be highly appreciated Smile

    Thanks

    Ron 
    Tuesday, December 22, 2009 11:28 PM

Answers

  • User-952121411 posted

    Well I have a couple of recommendations that could possibly improve your performance and make your code and methods use some more current technologies.

    1st off something not new, but the basis of setting up my recommendation later.  You mentioned you are loading 1000+ records.  In this case I would switch to a disconnected ADO.NET object using a DataAdapter and DataSet.  I know a DataReader is faster, but due to the amount of records you are fetching, + loading, + looping, + logic, you must keep that connection open to the database the entire time all of that processing is being done.  With a DataSet you can fetch all of the records and then close the connection to the database.  The DataReader is fast because it is a forward only 1-record-at-a-time fetch, but with the number of record being fetched you may want to switch.  Also a DataSet can contain multiple DataTables.  Each table can have relationships built and this could hep solve your issue from a purely ADO.NET standpoint, by creating a relationship between Person and Address and possibly making things easier in code.

    However with that said, the truly best way to process loading all of those record into a list of objects as you have done is with Linq.  I have used Linq to XML recently where I loaded over 800 records in (1) Linq statement, that previously would have taken 800 iterations of looping through the document with XPath.

    In your case you could look into Linq to Objects or Linq to DataSets.   You can probably reduce your looping to one main Linq query against the data.  In addition with Linq you can do JOINS and have WHERE clauses that should be able to solve your problem of knowing when the ID has changed.  This recommendation will take a little but of time and going through some tutorials to become familiar with it, but once you see the power, you will look at several parts of you code in a different way.

    The following links can help you get started:

    Language-Integrated Query (LINQ):

    http://msdn.microsoft.com/en-us/library/bb397926.aspx

    LINQ to Objects:

    http://msdn.microsoft.com/en-us/library/bb397919.aspx

    LINQ to ADO.NET:

    http://msdn.microsoft.com/en-us/library/bb397942.aspx

    LINQ to DataSet:

    http://msdn.microsoft.com/en-us/library/bb386977.aspx

    There are a ton and a half of great blog entries too by people such as Scott Guthrie and many others on how to use Linq if you need more information.

    Lastly, if you decide to stick with your current code, I don't think it is a bad method at all.  If I had the same setup as you, I probably would key off of the ID as well to see when it changes as a flag to add a new object to the list.

    Hope this helps! Smile

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, December 24, 2009 1:16 AM

All replies

  • User1692533347 posted

    Another way which i followed is

    There would be 2 different tables "Person" and "Address";

    first of all "select * from person"

    while dr.read()
    
    {
    
               p.ID=dr........
    
              p.name=dr......
    
               p.Addresses=this.GetAddressesByPersonID(PersonID)// another function returns 
                                 a collection of addresses based on person id,
                                 you can even pass a connection object to make sure only one connection is kept open while reading all persons
    
               PersonCollection.Add(p)
    
    }
    
    return PersonCollection
    



    Wednesday, December 23, 2009 5:50 AM
  • User102582072 posted

    Another way which i followed is

    There would be 2 different tables "Person" and "Address";

    first of all "select * from person"

    1. while dr.read()  
    2.   
    3. {  
    4.   
    5.            p.ID=dr........  
    6.   
    7.           p.name=dr......  
    8.   
    9.            p.Addresses=this.GetAddressesByPersonID(PersonID)// another function returns   
    10.                              a collection of addresses based on person id,  
    11.                              you can even pass a connection object to make sure only one connection is kept open while reading all persons  
    12.   
    13.            PersonCollection.Add(p)  
    14.   
    15. }  
    16.   
    17. return PersonCollection  

    Thanks for that, but the problem with that is its Ripple Loading. 

    Imagine trying to load 1,000 People, it will call the database 1,001 times (once for the initial 1,000 records, and once for each record)

    Basically what i'm trying to achieve is a way to create a generic class which lazy loads collections and their properties based on the Datareader.



    Wednesday, December 23, 2009 7:57 PM
  • User-952121411 posted

    Well I have a couple of recommendations that could possibly improve your performance and make your code and methods use some more current technologies.

    1st off something not new, but the basis of setting up my recommendation later.  You mentioned you are loading 1000+ records.  In this case I would switch to a disconnected ADO.NET object using a DataAdapter and DataSet.  I know a DataReader is faster, but due to the amount of records you are fetching, + loading, + looping, + logic, you must keep that connection open to the database the entire time all of that processing is being done.  With a DataSet you can fetch all of the records and then close the connection to the database.  The DataReader is fast because it is a forward only 1-record-at-a-time fetch, but with the number of record being fetched you may want to switch.  Also a DataSet can contain multiple DataTables.  Each table can have relationships built and this could hep solve your issue from a purely ADO.NET standpoint, by creating a relationship between Person and Address and possibly making things easier in code.

    However with that said, the truly best way to process loading all of those record into a list of objects as you have done is with Linq.  I have used Linq to XML recently where I loaded over 800 records in (1) Linq statement, that previously would have taken 800 iterations of looping through the document with XPath.

    In your case you could look into Linq to Objects or Linq to DataSets.   You can probably reduce your looping to one main Linq query against the data.  In addition with Linq you can do JOINS and have WHERE clauses that should be able to solve your problem of knowing when the ID has changed.  This recommendation will take a little but of time and going through some tutorials to become familiar with it, but once you see the power, you will look at several parts of you code in a different way.

    The following links can help you get started:

    Language-Integrated Query (LINQ):

    http://msdn.microsoft.com/en-us/library/bb397926.aspx

    LINQ to Objects:

    http://msdn.microsoft.com/en-us/library/bb397919.aspx

    LINQ to ADO.NET:

    http://msdn.microsoft.com/en-us/library/bb397942.aspx

    LINQ to DataSet:

    http://msdn.microsoft.com/en-us/library/bb386977.aspx

    There are a ton and a half of great blog entries too by people such as Scott Guthrie and many others on how to use Linq if you need more information.

    Lastly, if you decide to stick with your current code, I don't think it is a bad method at all.  If I had the same setup as you, I probably would key off of the ID as well to see when it changes as a flag to add a new object to the list.

    Hope this helps! Smile

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, December 24, 2009 1:16 AM