Я пытаюсь использовать NodaTime в своем приложении. Приложение сохраняет данные в базе данных mongodb. Рассмотрим следующий классКак пользовательский сериализатор влияет на поиск?
public class SomeType
{
public ObjectId Id { get; set; }
public Instant Instant { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
public DateTime DateTime { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
public DateTime DateTimeUtc { get; set; }
// public ZonedDateTime ZonedDateTime { get; set; }
// public LocalDateTime LocalDateTime { get; set; }
}
Без добавления пользовательского сериалайзер, то Instant
свойство класса не откладываются в БД. Чтение документа из db также не выполняется.
public class InstantBsonSerializer : BsonBaseSerializer
{
public override object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
{
var ticks = bsonReader.ReadInt64();
return new Instant(ticks);
}
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
var ticks = bsonReader.ReadInt64();
return new Instant(ticks);
}
public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
var instant = (Instant) value;
bsonWriter.WriteInt64(instant.Ticks);
}
}
Я создал вышеупомянутый сериализатор и зарегистрировал его должным образом. Теперь я могу сохранять и извлекать экземпляры моего класса с правильным значением, установленным для Instant
.
Мой вопрос в том, как обрабатывать дескриптор C# с помощью linq?
var list = mongoDatabase.GetCollection<SomeType>("SomeType")
.AsQueryable<SomeType>()
.Where(x => x.Instant < Instant.FromDateTimeUtc(dateTime.ToUniversalTime()))
.ToList();
Console.WriteLine(list.Count);
Я получаю правильный список документов. Я пытаюсь понять, КАК mongodb получает эти данные. Он сначала загружает ВСЕ данные, десериализует их правильно, а затем фильтрует? Или он сериализует значение Instant
значения предложения where и использует сериализованное значение для фильтрации всех документов, загрузки совпадающих и затем десериализации?
Я попытался просмотреть запрос, зарегистрированный профилировщиком mongodb, но его, похоже, ничего не записывает. Я установил уровень профилирования равным 2.
В случае Instant
сериализованное значение - long
. Но в случае ZonedDateTime
сериализованное значение будет документом с двумя свойствами. Как будет искать работу в этом случае?
Edit:
я смог профилирование работать. Следующий C# запрос,
mongoDatabase.GetCollection<SomeType>("SomeTypeCollection")
.AsQueryable<SomeType>()
.Where(x => x.Instant < Instant.FromDateTimeUtc(DateTime.UtcNow))
.ToList();
приводит к следующему MongoDB запроса
{ "Instant": { $lt: 13781017828460782 }}
Значение, C# драйвер сериализует мой Instant
объект и использует сериализированное значение для фильтрации результатов в самой БД.
Но предложение фильтра использует класс, для которого требуется собственный сериализатор. Как mongodb способен создать из него манго-запрос? Если бы я написал его как манго-запрос, я бы передал «bson object» в качестве значения для оператора '$ lt'. Но как драйвер C# представляет мой пользовательский сериализованный класс как объект bson? –
Из того, что я понимаю, драйвер будет использовать отражение, чтобы установить имена атрибутов для компиляции запроса так: var res = mongodb.GetCollection («MyColl»). AsQueryable() .Where (x => x.Prop == 123) 'будет компилировать запрос' {Prop: {$ eq: 123}} 'или' {Prop: 123} '- с помощью атрибута BsonElement можно управлять именем атрибута при сериализации и запросе. Как только запрос будет возвращен, драйвер будет десериализовать BsonDocument в объект. Карта классов по умолчанию, используемая для этого класса, будет использоваться, если вы используете сериализатор по умолчанию. –
sambomartin
стоит отметить, что вы можете запросить базу данных, проходящую в BsonDocument для запроса, возвращая курсор, который вы итерации возвращаете BsonDocument для каждого результата. Индивидуально каждый может быть десериализован в объект C# POCO. Если есть специальный сериализатор, зарегистрированный для определенного типа, он будет использоваться для гидратации объекта. – sambomartin