4

这就是我过去在实体框架 (POCO) 中利用继承的方式:

ctx.Animals // base class instances (all instances)
ctx.Animals.OfType<Cat>  // inherited class Cat's instances only
ctx.Animals.OfType<Dog> // inherited class Dog's instances only

这是我在 MongoDb(MongoDb 参考)中找到的唯一类似方式:

var query = Query.EQ("_t", "Cat");
var cursor = collection.FindAs<Animal>(query);

请注意,在后一种情况下,我必须处理鉴别器(“_t”)并对我的类名进行硬编码,这不太方便而且看起来很糟糕。如果我错过了查询,我会在枚举尝试时遇到异常。我错过了什么吗?我的建议是“按原样”存储对象的文档 Db 应该轻松处理继承。

4

5 回答 5

11

假设您的鉴别器正在运行(_t 为每个文档正确存储),那么我认为这就是您正在寻找的。

var results = collection.AsQueryable<Animal>().OfType<Cat>

仅返回那些类型为“Cat”的文档。

于 2014-03-17T18:18:41.080 回答
4

好吧,文档数据库实际上确实“按原样”存储对象——即没有属于某个特定类的对象的概念。这就是为什么_t当您希望反序列化器知道要实例化哪个子类时需要。

在您的情况下,我建议您为每个子类提出一个鉴别器,而不是依赖于类名。这样,您可以重命名类等,而不必担心某处的硬编码字符串。

你可以这样做:

public abstract class SomeBaseClass
{
    public const string FirstSubClass = "first";
    public const string SecondSubClass = "second";
}

[BsonDiscriminator(SomeBaseClass.FirstSubClass)]
public class FirstSubClass { ... }

接着

var entireCollection = db.GetCollection<FirstSubClass>("coll");

var subs = entireCollection.Find(Query.Eq("_t", SomeBaseClass.FirstSubClass));
于 2012-05-02T07:06:43.787 回答
1

From your link:

The one case where you must call RegisterClassMap yourself (even without arguments) is when you are using a polymorphic class hierarchy: in this case you must register all the known subclasses to guarantee that the discriminators get registered.


Register class maps for your base class and each one of your derived classes:

BsonClassMap.RegisterClassMap<Animal>();
BsonClassMap.RegisterClassMap<Cat>();
BsonClassMap.RegisterClassMap<Dog>();

Make sure that your collection is of type of your base class:

collection = db.GetCollection<Animal>("Animals");

Find using your query. The conversion to the corresponding child class is done automatically:

var query = Query.EQ("_t", "Cat");
var cursor = collection.Find(query);
于 2013-04-05T16:22:56.423 回答
0

如果唯一关心的是硬编码类名,您可以执行以下操作:

collection = db.GetCollection<Animal>("Animals");
var query = Query.EQ("_t", typeof(Cat).Name);
var cursor = collection.Find(query);
于 2014-04-03T10:00:44.110 回答
0

查看文档 http://docs.mongodb.org/ecosystem/tutorial/serialize-documents-with-the-csharp-driver/#scalar-and-hierarchical-discriminators

您可能选择使用分层鉴别器的主要原因是因为它可以查询层次结构中任何类的所有实例。例如,要读取我们可以编写的所有 Cat 文档:

var query = Query.EQ("_t", "Cat");
var cursor = collection.FindAs<Animal>(query);
foreach (var cat in cursor) {
    // process cat
}
于 2014-08-19T09:55:38.800 回答