使用C#MongoDB的LINQ与鉴别(Using C# MongoDB LINQ with dis

2019-09-20 00:10发布

我有一个单一的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中的特殊情况。

Answer 1:

当一个多态型层次结构的工作集合变量和你的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的类型。



Answer 2:

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



Answer 3:

就我而言,我需要的是能够检索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


Answer 4:

.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 ;
        }
    }
}


Answer 5:

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


文章来源: Using C# MongoDB LINQ with discriminator