This is how I used to utilize inheritance in Entity Framework (POCO):
ctx.Animals // base class instances (all instances)
ctx.Animals.OfType // inher
Take a look on the documentation http://docs.mongodb.org/ecosystem/tutorial/serialize-documents-with-the-csharp-driver/#scalar-and-hierarchical-discriminators
The main reason you might choose to use hierarchical discriminators is because it makes it possibly to query for all instances of any class in the hierarchy. For example, to read all the Cat documents we can write:
var query = Query.EQ("_t", "Cat");
var cursor = collection.FindAs<Animal>(query);
foreach (var cat in cursor) {
// process cat
}
From your link:
The one case where you must call RegisterClassMap yourself (even without arguments) is when you are using a polymorphic class hierarchy: in this case you must register all the known subclasses to guarantee that the discriminators get registered.
Register class maps for your base class and each one of your derived classes:
BsonClassMap.RegisterClassMap<Animal>();
BsonClassMap.RegisterClassMap<Cat>();
BsonClassMap.RegisterClassMap<Dog>();
Make sure that your collection is of type of your base class:
collection = db.GetCollection<Animal>("Animals");
Find using your query. The conversion to the corresponding child class is done automatically:
var query = Query.EQ("_t", "Cat");
var cursor = collection.Find(query);
If the only concern is hardcoding class name, you can do something like this:
collection = db.GetCollection<Animal>("Animals");
var query = Query.EQ("_t", typeof(Cat).Name);
var cursor = collection.Find(query);
Well, a document db does in fact store objects "as is" - i.e. without the notion of objects belonging to some particular class. That's why you need _t
when you want the deserializer to know which subclass to instantiate.
In your case, I suggest you come up with a discriminator for each subclass, instead of relying on the class name. This way, you can rename classes etc. without worrying about a hardcoded string somewhere.
You could do something like this:
public abstract class SomeBaseClass
{
public const string FirstSubClass = "first";
public const string SecondSubClass = "second";
}
[BsonDiscriminator(SomeBaseClass.FirstSubClass)]
public class FirstSubClass { ... }
and then
var entireCollection = db.GetCollection<FirstSubClass>("coll");
var subs = entireCollection.Find(Query.Eq("_t", SomeBaseClass.FirstSubClass));
Assuming your discriminators are functioning (_t is stored correctly for each document) then I think this is what you are looking for.
var results = collection.AsQueryable<Animal>().OfType<Cat>
Returns only those documents that are of type 'Cat'.