MongoDB via Dotnet Core数据映射详解 (5)

但是,如果是查询结果中有时间字段,那这个字段,会被DateTime默认设置为DateTimeKind.Unspecified类型。而这个类型,是无时区信息的,输出显示时,会造成混乱。

为了避免这种情况,在进行时间字段的映射时,需要加上属性:

[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
public DateTime post_time { get; set; }

这样做,会强制DateTime类型的字段为DateTimeKind.Local类型。这时候,从显示到使用就正确了。

但是,别高兴的太早,这儿还有一个但是。

这个但是是这样的:数据集中存放的是UTC时间,跟我们正常的时间有8小时时差,如果我们需要按日统计,比方每天的销售额/点击量,怎么搞?上面的方式,解决不了。

当然,基于MongoDB自由的字段处理,可以把需要统计的字段,按年月日时分秒拆开存放,像下面这样的:

class Post_Time
{

    public int year { get; set; }
    public int month { get; set; }
    public int day { get; set; }
    public int hour { get; set; }
    public int minute { get; set; }
    public int second { get; set; }
}

能解决,但是Low哭了有没有?

下面,终极方案来了。它就是:改写MongoDB中对于DateTime字段的序列化类。当当当~~~

先创建一个类MyDateTimeSerializer:

public class MyDateTimeSerializer : DateTimeSerializer
{
    public override DateTime Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    
{
        var obj = base.Deserialize(context, args);
        return new DateTime(obj.Ticks, DateTimeKind.Unspecified);
    }
    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DateTime value)
    
{
        var utcValue = new DateTime(value.Ticks, DateTimeKind.Utc);
        base.Serialize(context, args, utcValue);
    }
}

代码简单,一看就懂。

注意,使用这个方法,上边那个对于时间加的属性[BsonDateTimeOptions(Kind = DateTimeKind.Local)]一定不要添加,要不然就等着哭吧:P

创建完了,怎么用?

如果你只想对某个特定映射的特定字段使用,比方只对CollectionModel的post_time字段来使用,可以这么写:

[BsonSerializer(typeof(MyDateTimeSerializer))]
public DateTime post_time { get; set; }

或者全局使用:

BsonSerializer.RegisterSerializer(typeof(DateTime), new MongoDBDateTimeSerializer());

BsonSerializer是MongoDB.Driver的全局对象。所以这个代码,可以放到使用数据库前的任何地方。例如在Demo中,我放在Main里了:

static async Task Main(string[] args)
{
    BsonSerializer.RegisterSerializer(typeof(DateTime), new MyDateTimeSerializer());

    await Demo();
    Console.ReadKey();
}

这回看数据,数据集中的post_time跟当前时间显示完全一样了,你统计,你分组,可以随便霍霍了。

7. Dictionary字段

这个需求很奇怪。我们希望在一个Key-Value的文档中,保存一个Key-Value的数据。但这个需求又是真实存在的,比方保存一个用户的标签和标签对应的命中次数。

数据声明很简单:

public Dictionary<stringint> extra_info { get; set; }

MongoDB定义了三种保存属性:Document、ArrayOfDocuments、ArrayOfArrays,默认是Document。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspwzs.html