mongodb 这三个大坑踩过吗?( 二 )


mongodb 这三个大坑踩过吗?

文章插图
 
如果你想验证的话 , 可以继续用 dnspy 去验证一下源码哈 , 如下代码所示:
mongodb 这三个大坑踩过吗?

文章插图
 
接下来还有一种办法就是增加 _id 字段 , 如果你不知道用什么类型接 , 那就用object就好啦 , 后续再改成真正的类型 。
mongodb 这三个大坑踩过吗?

文章插图
 
2号坑 DateTime 时区不对如果你细心的话 , 你会发现刚才案例中的 Created 时间是 2020/8/16 4:24:57, 大家请放心 , 我不会傻到凌晨4点还在写代码 , 好了哈 , 看看到底问题在哪吧 ,  可以先看看 mongodb 中的记录数据,如下:
{"_id" : ObjectId("5f38b83e0351908eedac60c9"),"StudentName" : "hxc","Created" : ISODate("2020-08-16T04:38:22.587Z")}从 ISODate 可以看出 , 这是格林威治时间 , 按照0时区存储 , 所以这个问题转成了如何在获取数据的时候 , 自动将 ISO 时间转成 Local 时间就可以了 , 如果你看过底层源码 , 你会发现在 mongodb 中每个实体的每个类型都有一个专门的 XXXSerializer , 如下图:
mongodb 这三个大坑踩过吗?

文章插图
 
接下来就好好研读一下里面的 Deserialize 方法即可 , 代码精简后如下:
public override DateTime Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args){ IBsonReader bsonReader = context.Reader; BsonType currentBsonType = bsonReader.GetCurrentBsonType(); DateTime value;switch (this._kind) {case DateTimeKind.Unspecified:case DateTimeKind.Local:value = https://www.isolves.com/it/sjk/bk/2020-08-19/DateTime.SpecifyKind(BsonUtils.ToLocalTime(value), this._kind);break;case DateTimeKind.Utc:value = BsonUtils.ToUniversalTime(value);break; } return value;}可以看出 , 如果当前的 this._kind= DateTimeKind.Local 的话 , 就将 UTC 时间转成 Local 时间 , 如果你有上一个坑的经验 , 你大概就知道应该也是用特性注入的 , 
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]public DateTime Created { get; set; }不信的话 , 我调试给你看看哈 。
mongodb 这三个大坑踩过吗?

文章插图
 
接下来再看看 this._kind 是怎么被赋的 。
mongodb 这三个大坑踩过吗?

文章插图
 

mongodb 这三个大坑踩过吗?

文章插图
 
 3号坑 自定义ObjectID在第一个坑中 , 不知道大家看没看到类似这样的语句: ObjectId("5f38b83e0351908eedac60c9")  , 乍一看像是一个 GUID , 当然肯定不是 , 这是mongodb自己组建了一个 number 组合的十六进制表示 , 姑且不说性能如何 , 反正看着不是很舒服 , 毕竟大家都习惯使用 int/long 类型展示的主键ID 。
那接下来的问题是:如何改成我自定义的 number ID 呢? 当然可以 , 只要实现 IIdGenerator 接口即可 , 那主键ID的生成 , 我准备用 雪花算法 , 完整代码如下:
class Program{static void Main(string[] args){var client = new MongoClient("mongodb://192.168.1.128:27017");var database = client.GetDatabase("school");var table = database.GetCollection<Student>("student");table.InsertOne(new Student() { Created = DateTime.Now });table.InsertOne(new Student() { Created = DateTime.Now });}}class Student{[BsonId(IdGenerator = typeof(MyGenerator))]public long ID { get; set; }[BsonDateTimeOptions(Kind = DateTimeKind.Local)]public DateTime Created { get; set; }}public class MyGenerator : IIdGenerator{private static readonly IdWorker worker = new IdWorker(1, 1);public object GenerateId(object container, object document){return worker.NextId();}public bool IsEmpty(object id){return id == null || Convert.ToInt64(id) == 0;}}然后去看一下 mongodb 生成的 json:
mongodb 这三个大坑踩过吗?

文章插图
 
总结好了 , 这三个坑 , 我想很多刚接触 mongodb 的朋友是一定会遇到的困惑 , 总结一下方便后人乘凉 , 结果不重要 , 重要的还是探索问题的思路和不择手段 。


推荐阅读