热门标签 | 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();
     }
   }


推荐阅读
  • This guide provides a comprehensive step-by-step approach to successfully installing the MongoDB PHP driver on XAMPP for macOS, ensuring a smooth and efficient setup process. ... [详细]
  • dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用
    本文来安利大家一个有趣而且强大的库,通过F#和C#混合编程编写WPF应用,可以在WPF中使用到F#强大的数据处理能力在GitHub上完全开源Elmis ... [详细]
  • MongoDB的核心特性与架构解析
    本文深入探讨了MongoDB的核心特性,包括其强大的查询语言、灵活的文档模型以及高效的索引机制。此外,还详细介绍了MongoDB的体系结构,解释了其文档、集合和数据库的层次关系,并对比了MongoDB与传统关系型数据库(如MySQL)的逻辑结构。 ... [详细]
  • Mongoose 5.12.10 发布:MongoDB 异步对象模型工具的新特性与修复
    Mongoose 是一款专为异步环境设计的 MongoDB 对象模型工具,支持 Promise 和回调函数。最新版本 Mongoose 5.12.10 带来了多项修复和改进,包括查询选项中的默认值设置、嵌入式判别器填充、以及 TypeScript 定义文件的优化。 ... [详细]
  • 本文介绍了如何利用MongoDB的$exists操作符在Java应用程序中检查特定字段是否存在于文档中,包括示例代码和解释。 ... [详细]
  • 利用 Jest 和 Supertest 实现接口测试的全面指南
    本文深入探讨了如何使用 Jest 和 Supertest 进行接口测试,通过实际案例详细解析了测试环境的搭建、测试用例的编写以及异步测试的处理方法。 ... [详细]
  • 58同城的Elasticsearch应用与平台构建实践
    本文由58同城高级架构师于伯伟分享,由陈树昌编辑整理,内容源自DataFunTalk。文章探讨了Elasticsearch作为分布式搜索和分析引擎的应用,特别是在58同城的实施案例,包括集群优化、典型应用实例及自动化平台建设等方面。 ... [详细]
  • ODBC介绍:开放式数据库连接详解
    本文详细介绍了ODBC(开放式数据库连接),这是一种允许应用程序访问多种数据库系统的标准API。自1992年由微软与Simba合作推出以来,ODBC已成为跨平台数据访问的重要标准。 ... [详细]
  • 近期参与了一个旨在提高在线平台大规模查询响应速度的项目,预计处理的数据量为2-3亿条,数据库并发量约为每秒1500次,未来可能增至3000次。通过对比Redis和MongoDB,最终选择了MongoDB,因其具备优秀的横向扩展性和GridFS支持下的Map/Reduce功能。 ... [详细]
  • 本文详细介绍了如何构建MongoDB的ReplSet复制集群,包括环境准备、配置文件设置以及初始化复制集群的具体步骤。 ... [详细]
  • 开发笔记:Mongodb副本集集群搭建 ... [详细]
  • 使用 Docker 部署 MongoDB 并通过 IntelliJ IDEA 远程访问
    本文详细介绍了如何使用 Docker 部署 MongoDB,并通过 IntelliJ IDEA 实现远程连接的方法。包括 MongoDB 的基本配置、用户管理以及如何在 IDE 中配置连接。 ... [详细]
  • 本文深入探讨了分布式文件系统的核心概念及其在现代数据存储解决方案中的应用,特别是针对大规模数据处理的需求。文章不仅介绍了多种流行的分布式文件系统和NoSQL数据库,还提供了选择合适系统的指导原则。 ... [详细]
  • 程序员妻子吐槽:丈夫北漂8年终薪3万,存款情况令人意外
    一位程序员的妻子在网上分享了她丈夫在北京工作八年的经历,月薪仅3万元,存款情况却出乎意料。本文探讨了高学历人才在大城市的职场现状及生活压力。 ... [详细]
  • 本文详细介绍了 GWT 中 PopupPanel 类的 onKeyDownPreview 方法,提供了多个代码示例及应用场景,帮助开发者更好地理解和使用该方法。 ... [详细]
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社区 版权所有