Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using C# MongoDB LINQ with discriminator

I have a single MongoDB collection holding documents of three different classes (A,B,C) which all inherit from a common class D.

Using the official C# driver, I have inserted documents of all three types (A,B,C) and they all appear correctly with the _t discriminator, and in my code their class maps are registered.

If I issue a LINQ query such as the following (using VB):

dim Result = database.GetCollection("mycol").AsQueryable(Of C).Where(some where clause)

If I count the results of this, I am getting an error "Element 'an element name from class A' does not match any field or property of class C."

Isn't the discriminator meant to kick in here in the AsQueryable(Of C) code? It appears that when I issue .Count my Where clause, which is specific to elements of class C, is being applied to documents of A,B, and C.

I have tried adding .OfType(Of C) with no effect, have tried converting to a List first with .ToList, but I continue to get the same error. Any ideas?

As background, my client code will usually deal with objects of type D. A, B, C share a lot of common properties inherited from D which I want to put indexes on, hence I put them in a single collection. However, occassionally I need to directly reference an object of types A, B, or C in special circumstances.

like image 225
Greg May Avatar asked Jul 22 '12 00:07

Greg May


People also ask

What is using () in C#?

The using statement causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and can't be modified or reassigned. A variable declared with a using declaration is read-only.

Is Vs as C#?

The is operator returns true if the given object is of the same type, whereas the as operator returns the object when they are compatible with the given type. The is operator returns false if the given object is not of the same type, whereas the as operator returns null if the conversion is not possible.

Does using statement Call dispose?

The using statement guarantees that the object is disposed in the event an exception is thrown. It's the equivalent of calling dispose in a finally block.

What is the use of in front of a variable in C#?

What is the @ symbol in front of variables in C#? From the C# documentation it states that the @ symbol is an Identifier. The prefix “@” enables the use of keywords as identifiers, which is useful when interfacing with other programming languages.


1 Answers

When working with a polymorphic type hierarchy your collection variable and your LINQ queries should start in terms of the base class. For example, to read all the documents of type A back from the database you would write:

var collection = database.GetCollection<D>("mycol");
var query = collection.AsQueryable<D>().OfType<A>();
foreach (var a in query)
{
    // process document of type A
}

For diagnostic purposes you can see the corresponding native MongoDB query using:

var json = ((MongoQueryable<A>)query).GetMongoQuery().ToJson();

Note that you have to cast query to a MongoQueryable<A> (not MongoQueryable<D>) because the OfType() call changed the type of the IQueryable.

like image 143
Robert Stam Avatar answered Oct 10 '22 21:10

Robert Stam