5
\$\begingroup\$

I currently have a basic application that has a database backing it. I originally connected to the database with Entity Framework, but my tutor has requested from me to recreate the functionality with ADO.NET SQL. This has gone well so far using the SqlDataReader, however I have come across a problem.

My database stores a list of animals, the animals are Dog, Cat and Mouse, they all inherit from the Animal class. With entity framework when I wanted to get an animal from the database, it used the discriminator column automatically and I didn't have to worry about any logic to detect what type of animal the animal was. However so far the only way I can think of doing this with SQL is to manually check the discriminator column.

This works well for the moment but if I start adding say a hundred animals, it will become an impossible task to keep it working efficiently. My question is, is there another way to do this which is more elegant and will scale appropriately? The code for how I currently do the task is below:

if (reader.HasRows)
 {
 while (reader.Read())
 {
 if (reader.GetString(3) == "Dog")
 {
 list.Add(
 new Dog()
 {
 AnimalID = (int)reader.GetInt32(reader.GetOrdinal("AnimalID")),
 Name = (string)reader.GetString(reader.GetOrdinal("Name")),
 Age = (int)reader.GetInt32(reader.GetOrdinal("Age")),
 });
 }
 if (reader.GetString(3) == "Cat")
 {
 list.Add(
 new Cat()
 {
 AnimalID = (int)reader.GetInt32(reader.GetOrdinal("AnimalID")),
 Name = (string)reader.GetString(reader.GetOrdinal("Name")),
 Age = (int)reader.GetInt32(reader.GetOrdinal("Age")),
 });
 }
 if (reader.GetString(3) == "Mouse")
 {
 list.Add(
 new Mouse()
 {
 AnimalID = (int)reader.GetInt32(reader.GetOrdinal("AnimalID")),
 Name = (string)reader.GetString(reader.GetOrdinal("Name")),
 Age = (int)reader.GetInt32(reader.GetOrdinal("Age")),
 });
 }
 }
 }
 else
 {
 //no rows
 }
RubberDuck
31.1k6 gold badges73 silver badges176 bronze badges
asked Jan 9, 2014 at 9:07
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Could animals have properties, that extend base class? \$\endgroup\$ Commented Jan 9, 2014 at 9:12
  • \$\begingroup\$ No, the only real difference is the name. \$\endgroup\$ Commented Jan 9, 2014 at 9:13

1 Answer 1

5
\$\begingroup\$

Here is your code refactored - since all animals have id, name and age, you can remove duplication (reading and setting these properties for each type of animal):

if (reader.HasRows)
{
 while (reader.Read())
 {
 string animalType = reader.GetString(3);
 Animal animal = CreateAnimal(animalType);
 animal.AnimalID = (int)reader["AnimalID"];
 animal.Name = (string)reader["Name"];
 animal.Age = (int)reader["Age"]; 
 list.Add(animal); 
 }
}

Animal creation (if you are using type name as discriminator you can even use Activator.CreateInstance instead of this switch to create an instance of class):

private Animal CreateAnimal(string animalType)
{
 switch(animalType)
 {
 case "Dog": return new Dog();
 case "Cat": return new Cat(); 
 case "Mouse": return new Mouse(); 
 default:
 throw new ArgumentException();
 }
}
ChrisWue
20.6k4 gold badges42 silver badges107 bronze badges
answered Jan 9, 2014 at 9:11
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.