热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用C#生成MongoDB中ObjectId的方法

本篇文章小编为大家介绍,关于C#生成MongoDB中ObjectId的实现方法。需要的朋友参考下ObjectId介绍在MongoDB中,文档(document)在集合(collection)中的存储需要一个唯一的_id字段作为主键。这个_id默认使用ObjectId来定义,因为ObjectId定义的足够短小,

本篇文章小编为大家介绍,关于C#生成MongoDB中ObjectId的实现方法。需要的朋友参考下

ObjectId介绍
在MongoDB中,文档(document)在集合(collection)中的存储需要一个唯一的_id字段作为主键。这个_id默认使用ObjectId来定义,因为ObjectId定义的足够短小,并尽最大可能的保持唯一性,同时能被快速的生成。

ObjectId 是一个 12 Bytes 的 BSON 类型,其包含
1.4 Bytes 自纪元时间开始的秒数
2.3 Bytes 机器描述符
3.2 Bytes 进程ID
4.3 Bytes 随机数

从定义可以看出,在同一秒内,在不同的机器上相同进程ID条件下,非常有可能生成相同的ObjectId。
同时可以根据定义判断出,在给定条件下,ObjectId本身即可描述生成的时间顺序

ObjectId的存储使用Byte数组,而其展现需将Byte数组转换成字符串进行显示,所以通常我们看到的ObjectId都类似于:

ObjectId("507f191e810c19729de860ea")

C#定义ObjectId类

   public class ObjectId
   {
     private string _string;

     public ObjectId()
     {
     }

     public ObjectId(string value)
       : this(DecodeHex(value))
     {
     }

     internal ObjectId(byte[] value)
     {
       Value = value;
     }

     public static ObjectId Empty
     {
       get { return new ObjectId("000000000000000000000000"); }
     }

     public byte[] Value { get; private set; }

     public static ObjectId NewObjectId()
     {
       return new ObjectId { Value = ObjectIdGenerator.Generate() };
     }

     public static bool TryParse(string value, out ObjectId objectId)
     {
       objectId = Empty;
       if (value == null || value.Length != 24)
       {
         return false;
       }

       try
       {
         objectId = new ObjectId(value);
         return true;
       }
       catch (FormatException)
       {
         return false;
       }
     }

     protected static byte[] DecodeHex(string value)
     {
       if (string.IsNullOrEmpty(value))
         throw new ArgumentNullException("value");

       var chars = value.ToCharArray();
       var numberChars = chars.Length;
       var bytes = new byte[numberChars / 2];

       for (var i = 0; i < numberChars; i += 2)
       {
         bytes[i / 2] = Convert.ToByte(new string(chars, i, 2), 16);
       }

       return bytes;
     }

     public override int GetHashCode()
     {
       return Value != null ? ToString().GetHashCode() : 0;
     }

     public override string ToString()
     {
       if (_string == null && Value != null)
       {
         _string = BitConverter.ToString(Value)
.Replace("-", string.Empty)
.ToLowerInvariant();
       }

       return _string;
     }

     public override bool Equals(object obj)
     {
       var other = obj as ObjectId;
       return Equals(other);
     }

     public bool Equals(ObjectId other)
     {
       return other != null && ToString() == other.ToString();
     }

     public static implicit operator string(ObjectId objectId)
     {
       return objectId == null ? null : objectId.ToString();
     }

     public static implicit operator ObjectId(string value)
     {
       return new ObjectId(value);
     }

     public static bool operator ==(ObjectId left, ObjectId right)
     {
       if (ReferenceEquals(left, right))
       {
         return true;
       }

       if (((object)left == null) || ((object)right == null))
       {
         return false;
       }

       return left.Equals(right);
     }

     public static bool operator !=(ObjectId left, ObjectId right)
     {
       return !(left == right);
     }
   }

C#实现ObjectId的生成器

   internal static class ObjectIdGenerator
   {
     private static readonly DateTime Epoch =
       new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
     private static readonly object _innerLock = new object();
     private static int _counter;
     private static readonly byte[] _machineHash = GenerateHostHash();
     private static readonly byte[] _processId =
BitConverter.GetBytes(GenerateProcessId());

     public static byte[] Generate()
     {
       var oid = new byte[12];
       var copyidx = 0;

       Array.Copy(BitConverter.GetBytes(GenerateTime()), 0, oid, copyidx, 4);
       copyidx += 4;

       Array.Copy(_machineHash, 0, oid, copyidx, 3);
       copyidx += 3;

       Array.Copy(_processId, 0, oid, copyidx, 2);
       copyidx += 2;

       Array.Copy(BitConverter.GetBytes(GenerateCounter()), 0, oid, copyidx, 3);

       return oid;
     }

     private static int GenerateTime()
     {
       var now = DateTime.UtcNow;
       var nowtime = new DateTime(Epoch.Year, Epoch.Month, Epoch.Day,
         now.Hour, now.Minute, now.Second, now.Millisecond);
       var diff = nowtime - Epoch;
       return Convert.ToInt32(Math.Floor(diff.TotalMilliseconds));
     }

     private static byte[] GenerateHostHash()
     {
       using (var md5 = MD5.Create())
       {
         var host = Dns.GetHostName();
         return md5.ComputeHash(Encoding.Default.GetBytes(host));
       }
     }

     private static int GenerateProcessId()
     {
       var process = Process.GetCurrentProcess();
       return process.Id;
     }

     private static int GenerateCounter()
     {
       lock (_innerLock)
       {
         return _counter++;
       }
     }
   }

使用举例

class Program
   {
     static void Main(string[] args)
     {
       Console.ForegroundColor = ConsoleColor.Red;

       ObjectId emptyOid = ObjectId.Empty;
Console.WriteLine(emptyOid);

       Console.WriteLine();
       Console.ForegroundColor = ConsoleColor.Green;

       for (int i = 0; i <10; i++)
       {
         ObjectId oid = ObjectId.NewObjectId();
Console.WriteLine(oid);
       }

       Console.WriteLine();
       Console.ForegroundColor = ConsoleColor.Blue;

       ObjectId existingOid;
ObjectId.TryParse("507f191e810c19729de860ea", out existingOid);
Console.WriteLine(existingOid);

       Console.ReadKey();
     }
   }


推荐阅读
  • 本文是一位90后程序员分享的职业发展经验,从年薪3w到30w的薪资增长过程。文章回顾了自己的青春时光,包括与朋友一起玩DOTA的回忆,并附上了一段纪念DOTA青春的视频链接。作者还提到了一些与程序员相关的名词和团队,如Pis、蛛丝马迹、B神、LGD、EHOME等。通过分享自己的经验,作者希望能够给其他程序员提供一些职业发展的思路和启示。 ... [详细]
  • switch语句的一些用法及注意事项
    本文介绍了使用switch语句时的一些用法和注意事项,包括如何实现"fall through"、default语句的作用、在case语句中定义变量时可能出现的问题以及解决方法。同时也提到了C#严格控制switch分支不允许贯穿的规定。通过本文的介绍,读者可以更好地理解和使用switch语句。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • MongoDB用户验证auth的权限设置及角色说明
    本文介绍了MongoDB用户验证auth的权限设置,包括readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase、cluster相关的权限以及root权限等角色的说明和使用方法。 ... [详细]
  • Allegro总结:1.防焊层(SolderMask):又称绿油层,PCB非布线层,用于制成丝网印板,将不需要焊接的地方涂上防焊剂.在防焊层上预留的焊盘大小要比实际的焊盘大一些,其差值一般 ... [详细]
  • step1.为mongodb添加admin管理员root@12.154.29.163:~#mongoMongoDBshellversionv3.4.2connectingto:mo ... [详细]
  • 一、前言在数据库中,慢查询日志通常是用来进行优化数据库,MySQL中存在慢查询,Mongodb中也是如此。在Mongo中的慢查询属于Mon ... [详细]
  • Abp+MongoDb改造默认的审计日志存储位置
    一、背景在实际项目的开发当中,使用AbpZero自带的审计日志功能写入效率比较低。其次审计日志数据量中后期十分庞大,不适合与业务数据存放在一起。所以我们可以重新实现A ... [详细]
  • 今天我们学习,数据库mongodb的使用,最下面有mongodb的下载链接。pipinstallpymongo首先安装pymongo,然后在需要用到的地方importpymongo ... [详细]
  • MongoDB学习:(二)MongoDB简单使用
    MongoDB学习:(二)MongoDB简单使用MongoDB使用:执行mongodb的操作之前,我们需要运行命令,来进入操作命令界面&amp;amp;gt;mongo提示 ... [详细]
  •     系统采用jeeplus框架(ssm+redis+shiro+mongodb+redis),默认是做了JSP未做前后端分离,由于业务需要已经多终端使用的需求(H5、小程序等) ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
author-avatar
g37112969
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有