Reputation: 73163
This is a follow up to: Best way to save type of class in database?, well almost the same question but in a more general manner.
I often come across a situation where a base class/interface object has to be saved to database, and I need to read data back, instantiate as actual concrete objects and return a list.
A simple demo would explain it better.
interface IFeline
{
Name;
}
class Leopard
{
Name;
}
class Cheetah
{
Name;
}
I would be saving to database like this:
IFeline felix = new Cheetah();
felix.Save(); //saved to db
Now I need to get a list of felines from db.
public IEnumerable<IFeline> GetThemAll()
{
//connection
//query command
//reader
while(reader.Read())
yield return new ... { } //how do I get the actual felines here?
}
I hope the question is clear. I do not have separate tables for every concrete class They are all generic, and one table is sufficient to hold them.
I want to get the concrete instance from table. I know some sort of type information has to be saved along with the data. I can try a few approaches like saving type as string in the db table, or even enum to denote the type in database. Now my question is, is there a common approach/industry standard to tackle this problem?
Upvotes: 1
Views: 545
Reputation: 96
I am not sure how you are saving to the database. Are you serializing and then saving it to database or just plain text?
If you are serializing then easiest way is to deserialize and you will get proper object.
If you are saving each property to its appropriate column in database then you need to have one extra column to identify type of object.
while(reader.Read())
if type of object is 'Cheetah' then
Cheetah oFeline = new Cheetah { Name = "Cheetah_A" };
FelineList.Add(oFeline);
if type of object is 'Leopard' then
Leopard oFelineL = new Leopard { Name = "Leopard_A" };
FelineList.Add(oFelineL);
So now you have one list that includes both objects 'Cheetah and Leopard'
List<IFeline> FelineList = new List<IFeline>();
foreach (IFeline obj in FelineList) {
if ((obj) is Cheetah) {
ListBox1.Items.Add(obj.Name);
}
}
I hope that help!
Upvotes: 1
Reputation: 432
I don't know if this is a common approach or industry standard, but I think, as you mentioned, you could save the Type and assembly string along with the data. When getting them back, you could use Activator to return the proper type of object like this.
var assemblyName = reader["assembly_name"];
var typeName = reader["type_name"];
var instance = Activator.CreateInstance(assemblyName, typeName);
if (instance != null)
{
var feline = instance.Unwrap();
// reading object's properties
yield return feline;
}
Upvotes: 1