![mongodb 这三个大坑踩过吗?](http://img.jiangsulong.com/220421/032H2M37-4.jpg)
文章插图
如果你想验证的话 , 可以继续用 dnspy 去验证一下源码哈 , 如下代码所示:
![mongodb 这三个大坑踩过吗?](http://img.jiangsulong.com/220421/032H23603-5.jpg)
文章插图
接下来还有一种办法就是增加 _id 字段 , 如果你不知道用什么类型接 , 那就用object就好啦 , 后续再改成真正的类型 。
![mongodb 这三个大坑踩过吗?](http://img.jiangsulong.com/220421/032H224Z-6.jpg)
文章插图
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 这三个大坑踩过吗?](http://img.jiangsulong.com/220421/032H24431-7.jpg)
文章插图
接下来就好好研读一下里面的 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 这三个大坑踩过吗?](http://img.jiangsulong.com/220421/032H21C9-8.jpg)
文章插图
接下来再看看 this._kind 是怎么被赋的 。
![mongodb 这三个大坑踩过吗?](http://img.jiangsulong.com/220421/032H21295-9.jpg)
文章插图
![mongodb 这三个大坑踩过吗?](http://img.jiangsulong.com/220421/032H23236-10.jpg)
文章插图
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 这三个大坑踩过吗?](http://img.jiangsulong.com/220421/032H244A-11.jpg)
文章插图
总结好了 , 这三个坑 , 我想很多刚接触 mongodb 的朋友是一定会遇到的困惑 , 总结一下方便后人乘凉 , 结果不重要 , 重要的还是探索问题的思路和不择手段 。
推荐阅读
- laravel搭建博客实战的教程实例
- |工作中,总有这样那样的新问题
- 方舟|钓鲤鱼并非只能用玉米,这4种窝料都是鲤鱼最爱,老钓友都知道
- 什么是强迫症 有什么表现
- 积极阳光的走心句子有哪些?
- 每天做这运动让你心脏一生无忧
- 翡翠|先了解翡翠市场,然后再进行购买收藏,这才是正确的步骤
- 想要组装高性价比游戏主机,七彩虹这些硬件不容错过
- 用这几个工具,Windows下写代码比Linux还顺手
- 这4个简化流程是APP快速开发方式之一