2012-07-22 19 views
4

我有一个单一的MongoDB集合持有三种不同的类别(A,B,C),这都来自一个共同的D类放大器使用C#MongoDB的LINQ与鉴别

根据官方的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的对象。

回答

2

使用.AsQueryable<D>().OfType<C>.这应该有效地自动包含鉴别器。问题是我们不一定知道你使用的是A,B和C的相同集合,因此不知道当你做AsQueryable<C>()时,我们实际上需要添加一个鉴别器。我们将研究如何在未来实现更加无缝。

+0

克雷格您好,感谢这么多的快速答复。很遗憾没有区别。正如我在原来的帖子中提到的那样,我曾尝试过,但它似乎没有改变任何东西。是否有驱动程序随附的诊断程序,例如是否有可能看到底层查询?就像你可以用一个查询对象(即Query.ToString) – 2012-07-22 03:21:19

+0

我也尝试了'AsQueryable()。OfType(Of C)'而不是'AsQueryable(Of C).OfType(Of C)'并且得到了“No强制运算符定义在类型'MongoDB.Bson.BsonDocument'和'C'之间' – 2012-07-22 03:26:47

+0

还有一点评论:)我询问诊断的原因是我可以使用IMongoQuery发出几乎相同的命令,并且得到正确的结果。我试图使用泛型为我的非MongoDB意识类组成一个通用查询方法,因此LINQ适合这个账单。 – 2012-07-22 03:30:38

9

使用多态类型层次结构时,您的集合变量和LINQ查询应该以基类开始。例如,阅读类型的所有文件,从数据库中的回你可以这样写:

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的类型。

+0

这工作,谢谢你! – 2012-07-28 02:08:48

+2

神奇的块的信息。我鼓励你将它添加到mongodb文档中的Polymorphism部分(或者指出它是否已经存在) - 我知道我可以使用它。 – 2012-09-20 22:33:11

1

在我的情况下,我需要能够检索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 
0

我遇到了同样的问题:.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 ; 
     } 
    } 
} 
0

我使用的是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 
    } 
}