使用C#MongoDB LINQ和鉴别器

我有一个MongoDB集合,其中包含三个不同类(A,B,C)的文档,这些类都inheritance自公共类D.

使用官方C#驱动程序,我插入了所有三种类型(A,B,C)的文档,它们都与_t鉴别器一起正确显示,并且在我的代码中,他们的类映射被注册。

如果我发出LINQ查询,如下所示(使用VB):

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

如果我计算结果,我收到一个错误“元素’来自类A的元素名称’与类C的任何字段或属性都不匹配。”

判断器是不是要在AsQueryable(Of C)代码中AsQueryable(Of C) ? 当我发出.Count我的Where子句(特定于C类元素)被应用于A,B和C的文档。

我尝试添加.OfType(Of C)没有效果,尝试使用.ToList首先转换为List,但我继续得到相同的错误。 有任何想法吗?

作为背景,我的客户端代码通常会处理类型为D的对象.A,B,C共享许多从Dinheritance的公共属性,我想将索引放在上面,因此我把它们放在一个集合中。 但是,偶尔我需要在特殊情况下直接引用类型A,B或C的对象。

使用多态类型层次结构时,集合变量和LINQ查询应该从基类开始。 例如,要从数据库中读取所有类型A的文档,您将编写:

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

出于诊断目的,您可以使用以下方法查看相应的本机MongoDB查询:

 var json = ((MongoQueryable)query).GetMongoQuery().ToJson(); 

请注意,您必须将查询强制转换为MongoQueryable (而不是MongoQueryable ),因为OfType()调用更改了IQueryable的类型。

使用.AsQueryable().OfType. 这应该有效地包括鉴别器。 问题是我们不一定知道您对A,B和C使用相同的集合,因此不知道当您执行AsQueryable() ,我们实际上需要添加一个鉴别器。 我们将研究如何在未来使其更加无缝。

在我的情况下,我需要能够检索A,B,以及基类D. 所有这些都存储在同一个集合中。 这是我最终在我的存储库中做的事情:

    共享子新()
         BsonClassMap.RegisterClassMap(Of D)(
            子(F)
                 f.AutoMap()
                 f.SetIsRootClass(真)
            结束子)

         BsonClassMap.RegisterClassMap(Of A)()
         BsonClassMap.RegisterClassMap(Of B)()

    结束子

这有效地将基类和子类都添加到鉴别器中。

 _t:D,A

然后,它允许我查询这两种类型。

 Dim collection = _db.GetCollection(D)(“Items”)

 Dim resultA = collection.AsQueryable()。OfType(of A)'只输入A'
 Dim resultB = collection.AsQueryable()。OfType(of B)'只有B型
 Dim resultD = collection.AsQueryable()。OfType(of D)'A和B都是基类

我遇到了同样的问题:.AsQueryable()和OfType()都不会在查询中产生“_t”鉴别器。 特别是当你有一个高级通用OpenQuery()方法时,你可以将IQueryable接口公开给任何插件,而不需要Mongo驱动程序库引用。 无论如何,如果使用静态类来访问集合,告诉BsonClassMap特定类是root将解决此问题。

 // Data Repository class public static class MyDataRepositoryMethods { static MyDataRepositoryMethods() { BsonClassMap.RegisterClassMap(x => { x.AutoMap(); x.SetIsRootClass(true); }); } ///  /// Returns a queryable data sample collection ///  ///  ///  public static IQueryable OpenQuery() where TMyBaseClassOfStuff: MyBaseClassOfStuff { using (var storage = new MongoDataStorageStuff()) { // _t discriminator will reflect the final class, not the base class (unless you pass generic type info of the base class var dataItems = storage.GetCollection("abcdef").OfType(); return dataItems ; } } } 

我正在使用C#驱动程序v1.9.2但似乎这是在v1.4.1中引入的。

 collection = MongoDatabase.GetCollection("MyCollectionName"); long count = collection.AsQueryable().OfType().Count(); 

个人资料包含:

 command: { "count" : "MyCollectionName", "query" : { "_t" : "D" // MyDerivedClass discriminator value } }