我正在尝试在我的应用中使用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如何获取此数据。它首先加载所有数据,正确反序列化然后过滤?或者它是否序列化where子句的Instant
值并使用序列化值过滤所有文档,加载匹配的文档然后反序列化?
我试过看到mongodb探查器记录的查询,但它似乎没有记录任何东西。我已将分析级别设置为2。
对于Instant
,序列化值为long
。但是在ZonedDateTime
的情况下,序列化值将是具有两个属性的文档。在这种情况下如何搜索工作?
修改
我能够使分析工作。以下c#查询,
mongoDatabase.GetCollection<SomeType>("SomeTypeCollection")
.AsQueryable<SomeType>()
.Where(x => x.Instant < Instant.FromDateTimeUtc(DateTime.UtcNow))
.ToList();
导致以下mongodb查询
{ "Instant": { $lt: 13781017828460782 }}
意思是,c#驱动程序序列化我的Instant
对象并使用序列化值来过滤db本身的结果。
答案 0 :(得分:1)
驱动程序会将linq查询转换为mongodb查询并在反序列化之前过滤结果。在您致电ToList()
以下是受支持的运营商:http://docs.mongodb.org/ecosystem/tutorial/use-linq-queries-with-csharp-driver/
在驱动程序从返回的数据开始构建对象图之前,自定义反序列化器不会发挥作用。
对于简单类型的类或者在阅读/编写文档时没有做额外工作的情况,通常不需要自定义序列化程序。
如果你想控制序列化的内容,即基本上你的类只保存一个日期时间,为什么不这样做才能存储UTC日期时间戳,并使用BsonIgnore
来表示其他属性。