使用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
使用.AsQueryable
这应该有效地包括鉴别器。 问题是我们不一定知道您对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 } }