What is the best approach at the repository level to hydrate an object’s sub entities. For example: I need a list of all people in the system. Each person can have many phone numbers. How would I go about filling all this data in my repository?
public class Person
{
public int? Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public List<Phone> PhoneNumbers { get; set; }
}
public IEnumerable<Person> GetPeople()
{
var persons = new List<Person>();
const string sql = "SELECT FirstName, LastName, MiddleName FROM Person.Person";
while (reader.Read())
{
var p = PersonFactory.GetPerson(reader);
p.PhoneNumbers = this.GetPhoneByPersonId(p.Id);
persons.Add(p);
}
return persons;
}
public IEnumerable<Phone> GetPhoneByPersonId(int? id)
{
while (reader.Read())
{
numbers.Add(PersonFactory.GetPhone(reader));
}
}
My problem with this approach is that I’m executing a bunch of sql statements that hit the DB. That just doesn’t seem like the best approach. I cannot use any frameworks and must use a DataReader.
What is a better approach I could take? Also this is a simple example. There will be many more lists with my Person object.
One approach to implementing the
GetPeoplemethod would be execute a single SQL statement containing multiple result sets. If using SQL Server with MARS enabled, this will come from the server as a response to a single query. Otherwise, you can execute two queries, one to retrieve the people and another to retrieve all phone numbers that would be associated with those people.Your queries can look something like:
Again, you can either send both queries in a single command if the server supports it, or issue two separate queries. Either way, that is only two queries, which is no big deal. Do make sure that you aren’t returning too many results at once.
Once you have the two result sets in memory, you can join them by person ID and associate all people instances with their corresponding phone numbers. Overall, you are doing either one or two database queries.
The IDataReader provides the method NextResult to enumerate multiple result sets returned by the query.