关于C#生成MongoDB中ObjectId的实现方法
更新时间:2020年6月25日 11:42 点击:1581
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类
复制代码 代码如下:
View Code
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的生成器
复制代码 代码如下:
View Code
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();
}
}
相关文章
- 由于要使用mikoomi mongodb plugin插件,所以需要php对mongodb的扩展支持,默认通过源安装的php并没有mongodb的扩展支持,具体可以通过php -m|grep mongo 验证 。这里就结...2016-11-25
- 我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
- 这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
- 这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
- 本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
- 这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)
这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25- 这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
- 这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
- 最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
- 这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
- 本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
- 轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
- 这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
- 本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
- 这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
- 下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25