我有一个单一的MongoDB集合持有三种不同的类别(A,B,C),这都来自一个共同的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)
的代码? 看来,当我发出.Count
我的Where子句,这是专门针对C类的元素,被应用到A,B和C的文件
我曾尝试加入.OfType(Of C)
没有效果,曾尝试与转换为列表第一.ToList
,但我仍然得到同样的错误。 有任何想法吗?
作为背景,我的客户端代码通常会处理型D. A,B的对象,C有许多共同的属性,从d我希望把指标上继承而来的,所以我把它们放在一个单一的集合。 然而,偶尔我需要直接引用的类型的对象A,B,或C中的特殊情况。
当一个多态型层次结构的工作集合变量和你的LINQ查询应在基类的条款开始。 例如,读取A型从你会写数据库返回的所有文档:
var collection = database.GetCollection<D>("mycol");
var query = collection.AsQueryable<D>().OfType<A>();
foreach (var a in query)
{
// process document of type A
}
为了诊断,你可以看到使用相应的本地MongoDB的查询:
var json = ((MongoQueryable<A>)query).GetMongoQuery().ToJson();
需要注意的是,你要投的查询到MongoQueryable <A>(不MongoQueryable <d>),因为OfType()调用改变了IQueryable的类型。
使用.AsQueryable<D>().OfType<C>.
这应该有效地自动包括鉴别。 问题是,我们并不一定知道你正在使用A,B和C相同的集合,因此不知道,当你做AsQueryable<C>()
我们确实需要添加一个鉴别。 我们将寻找到如何使这个在未来更加无缝。
就我而言,我需要的是能够检索A,B,以及d,基类。 所有这些都存储在同一个收藏。 这是我结束了在我的仓库做:
Shared Sub New()
BsonClassMap.RegisterClassMap(Of D)(
Sub(f)
f.AutoMap()
f.SetIsRootClass(True)
End Sub)
BsonClassMap.RegisterClassMap(Of A)()
BsonClassMap.RegisterClassMap(Of B)()
End Sub
这有效地增加了基类和子类来鉴别两者。
_t: D, A
然后让我查询两种类型。
Dim collection = _db.GetCollection(of D)("Items")
Dim resultA = collection.AsQueryable().OfType(of A) ' Only type A's
Dim resultB = collection.AsQueryable().OfType(of B) ' Only type B's
Dim resultD = collection.AsQueryable().OfType(of D) ' Both A's and B's as the base class
.AsQueryable()既不也不OfType()会产生在查询“_t”鉴:我遇到了同样的问题。 尤其是当你有一个高层次的通用OPENQUERY()方法,这样就可以公开的IQueryable接口,没有他们任何插件需要Mongo的驱动程序库的参考。 总之,如果使用的是静态类访问您的收藏,告诉BsonClassMap,具体的类是根将解决这个问题。
// Data Repository class
public static class MyDataRepositoryMethods
{
static MyDataRepositoryMethods()
{
BsonClassMap.RegisterClassMap<MyBaseClassOfStuff>(x =>
{
x.AutoMap();
x.SetIsRootClass(true);
});
}
/// <summary>
/// Returns a queryable data sample collection
/// </summary>
/// <typeparam name="TMyBaseClassOfStuff"></typeparam>
/// <returns></returns>
public static IQueryable<TMyBaseClassOfStuff> OpenQuery<TMyBaseClassOfStuff>() 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<TMyBaseClassOfStuff>("abcdef").OfType<TMyBaseClassOfStuff>();
return dataItems ;
}
}
}
我使用C#驱动程序v1.9.2的,但似乎这是介绍早在V1.4.1。
collection = MongoDatabase.GetCollection<MyBaseClass>("MyCollectionName");
long count = collection.AsQueryable().OfType<MyDerivedClass>().Count();
配置文件包含此:
command: {
"count" : "MyCollectionName",
"query" : {
"_t" : "D" // MyDerivedClass discriminator value
}
}