Наследование в MongoDb: как запрашивать экземпляры определенного типа

Вот как я использовал наследование в Entity Framework (POCO):

<code>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
</code>

Это единственный подобный способ, который я нашел в MongoDb (MongoDb ссылка):

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

Обратите внимание, что в последнем случае мне приходится иметь дело с дискриминатором (& quot; _t & quot;) и жестким кодом моего имени класса, что не совсем удобно и выглядит ужасно. Если я пропускаю запрос, я получаю исключение при попытке перечисления. Я что-то пропустил? Моим предложением был документ Db, в котором хранятся объекты «как есть». должен легко обрабатывать наследство.

Ответы на вопрос(5)

твоя ссылка:

Единственный случай, когда вы должны вызвать RegisterClassMap самостоятельно (даже без аргументов), это когда вы используете полиморфную иерархию классов: в этом случае вы должны зарегистрировать все известные подклассы, чтобы гарантировать, что дискриминаторы будут зарегистрированы.


Зарегистрируйте карты классов для вашего базового класса и каждого из ваших производных классов:

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

Убедитесь, что ваша коллекция относится к типу вашего базового класса:

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

Найдите, используя ваш запрос. Преобразование в соответствующий дочерний класс выполняется автоматически:

var query = Query.EQ("_t", "Cat");
var cursor = collection.Find(query);

http: //docs.mongodb.org/ecosystem/tutorial/serialize-documents-with-the-csharp-driver/#scalar-and-hierarchical-discriminator

Основная причина, по которой вы можете выбрать использование иерархических дискриминаторов, заключается в том, что он позволяет запрашивать все экземпляры любого класса в иерархии. Например, чтобы прочитать все документы Cat, которые мы можем написать:

var query = Query.EQ("_t", "Cat");
var cursor = collection.FindAs<Animal>(query);
foreach (var cat in cursor) {
    // process cat
}

документ БД фактически хранит объекты «как есть», то есть без понятия объектов, принадлежащих к какому-то определенному классу. Вот почему вам нужно_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));

что ваши дискриминаторы работают (_t хранится правильно для каждого документа), то я думаю, что это то, что вы ищете.

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

Возвращает только те документы, которые имеют тип «Cat».

са, вы можете сделать что-то вроде этого:

collection = db.GetCollection<Animal>("Animals");
var query = Query.EQ("_t", typeof(Cat).Name);
var cursor = collection.Find(query);

ВАШ ОТВЕТ НА ВОПРОС