公众平台微信公众号官网,wordpress仿seowhy基础指南模板,温州网站建设seo,南昌做网站哪个好前言
因为很多场景下我们需要在创建MongoDB数据的时候提前生成好主键为了返回或者通过主键查询创建的业务#xff0c;像EF中我们可以生成Guid来#xff0c;本来想着要不要实现一套MongoDB中ObjectId的#xff0c;结果发现网上各种各样的实现都有#xff0c;不过好在阅读C#…前言
因为很多场景下我们需要在创建MongoDB数据的时候提前生成好主键为了返回或者通过主键查询创建的业务像EF中我们可以生成Guid来本来想着要不要实现一套MongoDB中ObjectId的结果发现网上各种各样的实现都有不过好在阅读C#MongoDB驱动mongo-csharp-driver代码的时候发现有ObjectId.GenerateNewId()的方法提供我们可以直接调用即可不需要我们在花费多余的时间设计重写了。 MongoDB ObjectId类型概述 每次插入一条数据系统都会自动插入一个_id键键值不可以重复它可以是任何类型的也可以手动的插入默认情况下它的数据类型是ObjectId由于MongoDB在设计之初就是用作分布式数据库所以使用ObjectId可以避免不同数据库中_id的重复如果使用自增的方式在分布式系统中就会出现重复的_id的值。 ObjectId使用12字节的存储空间每个字节可以存储两个十六进制数字所以一共可以存储24个十六进制数字组成的字符串在这24个字符串中前8位表示时间戳接下来6位是一个机器码接下来4位表示进程id最后6位表示计数器。 MongoDB 采用 ObjectId 来表示主键的类型数据库中每个文档都拥有一个_id 字段表示主键_id 的生成规则如下 其中包括4-byte Unix 时间戳3-byte 机器 ID2-byte 进程 ID3-byte 计数器(初始化随机)。 601e2b6b a3203c c89f 2d31aa↑ ↑ ↑ ↑时间戳 机器码 进程ID 随机数 MongoDB.Driver驱动安装
1、直接命令自动安装
Install-Package MongoDB.Driver
2、搜索Nuget手动安装 调用生成主键ObjectId
var primarykeyId ObjectId.GenerateNewId();
//输出641c54b2e674000035001dc2 mongo-csharp-driver ObjectId详解 关于ObjectId的生成原理大家阅读如下源码即可。 源码地址https://github.com/mongodb/mongo-csharp-driver/blob/ec74978f7e827515f29cc96fba0c727828e8df7c/src/MongoDB.Bson/ObjectModel/ObjectId.cs
/* Copyright 2010-present MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Security;
using System.Threading;namespace MongoDB.Bson
{/// summary/// Represents an ObjectId (see also BsonObjectId)./// /summary
#if NET45[Serializable]
#endifpublic struct ObjectId : IComparableObjectId, IEquatableObjectId, IConvertible{// private static fieldsprivate static readonly ObjectId __emptyInstance default(ObjectId);private static readonly int __staticMachine (GetMachineHash() GetAppDomainId()) 0x00ffffff;private static readonly short __staticPid GetPid();private static int __staticIncrement (new Random()).Next();// private fieldsprivate readonly int _a;private readonly int _b;private readonly int _c;// constructors/// summary/// Initializes a new instance of the ObjectId class./// /summary/// param namebytesThe bytes./parampublic ObjectId(byte[] bytes){if (bytes null){throw new ArgumentNullException(bytes);}if (bytes.Length ! 12){throw new ArgumentException(Byte array must be 12 bytes long, bytes);}FromByteArray(bytes, 0, out _a, out _b, out _c);}/// summary/// Initializes a new instance of the ObjectId class./// /summary/// param namebytesThe bytes./param/// param nameindexThe index into the byte array where the ObjectId starts./paraminternal ObjectId(byte[] bytes, int index){FromByteArray(bytes, index, out _a, out _b, out _c);}/// summary/// Initializes a new instance of the ObjectId class./// /summary/// param nametimestampThe timestamp (expressed as a DateTime)./param/// param namemachineThe machine hash./param/// param namepidThe PID./param/// param nameincrementThe increment./parampublic ObjectId(DateTime timestamp, int machine, short pid, int increment): this(GetTimestampFromDateTime(timestamp), machine, pid, increment){}/// summary/// Initializes a new instance of the ObjectId class./// /summary/// param nametimestampThe timestamp./param/// param namemachineThe machine hash./param/// param namepidThe PID./param/// param nameincrementThe increment./parampublic ObjectId(int timestamp, int machine, short pid, int increment){if ((machine 0xff000000) ! 0){throw new ArgumentOutOfRangeException(machine, The machine value must be between 0 and 16777215 (it must fit in 3 bytes).);}if ((increment 0xff000000) ! 0){throw new ArgumentOutOfRangeException(increment, The increment value must be between 0 and 16777215 (it must fit in 3 bytes).);}_a timestamp;_b (machine 8) | (((int)pid 8) 0xff);_c ((int)pid 24) | increment;}/// summary/// Initializes a new instance of the ObjectId class./// /summary/// param namevalueThe value./parampublic ObjectId(string value){if (value null){throw new ArgumentNullException(value);}var bytes BsonUtils.ParseHexString(value);FromByteArray(bytes, 0, out _a, out _b, out _c);}// public static properties/// summary/// Gets an instance of ObjectId where the value is empty./// /summarypublic static ObjectId Empty{get { return __emptyInstance; }}// public properties/// summary/// Gets the timestamp./// /summarypublic int Timestamp{get { return _a; }}/// summary/// Gets the machine./// /summarypublic int Machine{get { return (_b 8) 0xffffff; }}/// summary/// Gets the PID./// /summarypublic short Pid{get { return (short)(((_b 8) 0xff00) | ((_c 24) 0x00ff)); }}/// summary/// Gets the increment./// /summarypublic int Increment{get { return _c 0xffffff; }}/// summary/// Gets the creation time (derived from the timestamp)./// /summarypublic DateTime CreationTime{get { return BsonConstants.UnixEpoch.AddSeconds(Timestamp); }}// public operators/// summary/// Compares two ObjectIds./// /summary/// param namelhsThe first ObjectId./param/// param namerhsThe other ObjectId/param/// returnsTrue if the first ObjectId is less than the second ObjectId./returnspublic static bool operator (ObjectId lhs, ObjectId rhs){return lhs.CompareTo(rhs) 0;}/// summary/// Compares two ObjectIds./// /summary/// param namelhsThe first ObjectId./param/// param namerhsThe other ObjectId/param/// returnsTrue if the first ObjectId is less than or equal to the second ObjectId./returnspublic static bool operator (ObjectId lhs, ObjectId rhs){return lhs.CompareTo(rhs) 0;}/// summary/// Compares two ObjectIds./// /summary/// param namelhsThe first ObjectId./param/// param namerhsThe other ObjectId./param/// returnsTrue if the two ObjectIds are equal./returnspublic static bool operator (ObjectId lhs, ObjectId rhs){return lhs.Equals(rhs);}/// summary/// Compares two ObjectIds./// /summary/// param namelhsThe first ObjectId./param/// param namerhsThe other ObjectId./param/// returnsTrue if the two ObjectIds are not equal./returnspublic static bool operator !(ObjectId lhs, ObjectId rhs){return !(lhs rhs);}/// summary/// Compares two ObjectIds./// /summary/// param namelhsThe first ObjectId./param/// param namerhsThe other ObjectId/param/// returnsTrue if the first ObjectId is greather than or equal to the second ObjectId./returnspublic static bool operator (ObjectId lhs, ObjectId rhs){return lhs.CompareTo(rhs) 0;}/// summary/// Compares two ObjectIds./// /summary/// param namelhsThe first ObjectId./param/// param namerhsThe other ObjectId/param/// returnsTrue if the first ObjectId is greather than the second ObjectId./returnspublic static bool operator (ObjectId lhs, ObjectId rhs){return lhs.CompareTo(rhs) 0;}// public static methods/// summary/// Generates a new ObjectId with a unique value./// /summary/// returnsAn ObjectId./returnspublic static ObjectId GenerateNewId(){return GenerateNewId(GetTimestampFromDateTime(DateTime.UtcNow));}/// summary/// Generates a new ObjectId with a unique value (with the timestamp component based on a given DateTime)./// /summary/// param nametimestampThe timestamp component (expressed as a DateTime)./param/// returnsAn ObjectId./returnspublic static ObjectId GenerateNewId(DateTime timestamp){return GenerateNewId(GetTimestampFromDateTime(timestamp));}/// summary/// Generates a new ObjectId with a unique value (with the given timestamp)./// /summary/// param nametimestampThe timestamp component./param/// returnsAn ObjectId./returnspublic static ObjectId GenerateNewId(int timestamp){int increment Interlocked.Increment(ref __staticIncrement) 0x00ffffff; // only use low order 3 bytesreturn new ObjectId(timestamp, __staticMachine, __staticPid, increment);}/// summary/// Packs the components of an ObjectId into a byte array./// /summary/// param nametimestampThe timestamp./param/// param namemachineThe machine hash./param/// param namepidThe PID./param/// param nameincrementThe increment./param/// returnsA byte array./returnspublic static byte[] Pack(int timestamp, int machine, short pid, int increment){if ((machine 0xff000000) ! 0){throw new ArgumentOutOfRangeException(machine, The machine value must be between 0 and 16777215 (it must fit in 3 bytes).);}if ((increment 0xff000000) ! 0){throw new ArgumentOutOfRangeException(increment, The increment value must be between 0 and 16777215 (it must fit in 3 bytes).);}byte[] bytes new byte[12];bytes[0] (byte)(timestamp 24);bytes[1] (byte)(timestamp 16);bytes[2] (byte)(timestamp 8);bytes[3] (byte)(timestamp);bytes[4] (byte)(machine 16);bytes[5] (byte)(machine 8);bytes[6] (byte)(machine);bytes[7] (byte)(pid 8);bytes[8] (byte)(pid);bytes[9] (byte)(increment 16);bytes[10] (byte)(increment 8);bytes[11] (byte)(increment);return bytes;}/// summary/// Parses a string and creates a new ObjectId./// /summary/// param namesThe string value./param/// returnsA ObjectId./returnspublic static ObjectId Parse(string s){if (s null){throw new ArgumentNullException(s);}ObjectId objectId;if (TryParse(s, out objectId)){return objectId;}else{var message string.Format({0} is not a valid 24 digit hex string., s);throw new FormatException(message);}}/// summary/// Tries to parse a string and create a new ObjectId./// /summary/// param namesThe string value./param/// param nameobjectIdThe new ObjectId./param/// returnsTrue if the string was parsed successfully./returnspublic static bool TryParse(string s, out ObjectId objectId){// dont throw ArgumentNullException if s is nullif (s ! null s.Length 24){byte[] bytes;if (BsonUtils.TryParseHexString(s, out bytes)){objectId new ObjectId(bytes);return true;}}objectId default(ObjectId);return false;}/// summary/// Unpacks a byte array into the components of an ObjectId./// /summary/// param namebytesA byte array./param/// param nametimestampThe timestamp./param/// param namemachineThe machine hash./param/// param namepidThe PID./param/// param nameincrementThe increment./parampublic static void Unpack(byte[] bytes, out int timestamp, out int machine, out short pid, out int increment){if (bytes null){throw new ArgumentNullException(bytes);}if (bytes.Length ! 12){throw new ArgumentOutOfRangeException(bytes, Byte array must be 12 bytes long.);}timestamp (bytes[0] 24) (bytes[1] 16) (bytes[2] 8) bytes[3];machine (bytes[4] 16) (bytes[5] 8) bytes[6];pid (short)((bytes[7] 8) bytes[8]);increment (bytes[9] 16) (bytes[10] 8) bytes[11];}// private static methodsprivate static int GetAppDomainId(){
#if NETSTANDARD1_5 || NETSTANDARD1_6return 1;
#elsereturn AppDomain.CurrentDomain.Id;
#endif}/// summary/// Gets the current process id. This method exists because of how CAS operates on the call stack, checking/// for permissions before executing the method. Hence, if we inlined this call, the calling method would not execute/// before throwing an exception requiring the try/catch at an even higher level that we dont necessarily control./// /summary[MethodImpl(MethodImplOptions.NoInlining)]private static int GetCurrentProcessId(){return Process.GetCurrentProcess().Id;}private static int GetMachineHash(){// use instead of Dns.HostName so it will work offlinevar machineName GetMachineName();return 0x00ffffff machineName.GetHashCode(); // use first 3 bytes of hash}private static string GetMachineName(){return Environment.MachineName;}private static short GetPid(){try{return (short)GetCurrentProcessId(); // use low order two bytes only}catch (SecurityException){return 0;}}private static int GetTimestampFromDateTime(DateTime timestamp){var secondsSinceEpoch (long)Math.Floor((BsonUtils.ToUniversalTime(timestamp) - BsonConstants.UnixEpoch).TotalSeconds);if (secondsSinceEpoch int.MinValue || secondsSinceEpoch int.MaxValue){throw new ArgumentOutOfRangeException(timestamp);}return (int)secondsSinceEpoch;}private static void FromByteArray(byte[] bytes, int offset, out int a, out int b, out int c){a (bytes[offset] 24) | (bytes[offset 1] 16) | (bytes[offset 2] 8) | bytes[offset 3];b (bytes[offset 4] 24) | (bytes[offset 5] 16) | (bytes[offset 6] 8) | bytes[offset 7];c (bytes[offset 8] 24) | (bytes[offset 9] 16) | (bytes[offset 10] 8) | bytes[offset 11];}// public methods/// summary/// Compares this ObjectId to another ObjectId./// /summary/// param nameotherThe other ObjectId./param/// returnsA 32-bit signed integer that indicates whether this ObjectId is less than, equal to, or greather than the other./returnspublic int CompareTo(ObjectId other){int result ((uint)_a).CompareTo((uint)other._a);if (result ! 0) { return result; }result ((uint)_b).CompareTo((uint)other._b);if (result ! 0) { return result; }return ((uint)_c).CompareTo((uint)other._c);}/// summary/// Compares this ObjectId to another ObjectId./// /summary/// param namerhsThe other ObjectId./param/// returnsTrue if the two ObjectIds are equal./returnspublic bool Equals(ObjectId rhs){return_a rhs._a _b rhs._b _c rhs._c;}/// summary/// Compares this ObjectId to another object./// /summary/// param nameobjThe other object./param/// returnsTrue if the other object is an ObjectId and equal to this one./returnspublic override bool Equals(object obj){if (obj is ObjectId){return Equals((ObjectId)obj);}else{return false;}}/// summary/// Gets the hash code./// /summary/// returnsThe hash code./returnspublic override int GetHashCode(){int hash 17;hash 37 * hash _a.GetHashCode();hash 37 * hash _b.GetHashCode();hash 37 * hash _c.GetHashCode();return hash;}/// summary/// Converts the ObjectId to a byte array./// /summary/// returnsA byte array./returnspublic byte[] ToByteArray(){var bytes new byte[12];ToByteArray(bytes, 0);return bytes;}/// summary/// Converts the ObjectId to a byte array./// /summary/// param namedestinationThe destination./param/// param nameoffsetThe offset./parampublic void ToByteArray(byte[] destination, int offset){if (destination null){throw new ArgumentNullException(destination);}if (offset 12 destination.Length){throw new ArgumentException(Not enough room in destination buffer., offset);}destination[offset 0] (byte)(_a 24);destination[offset 1] (byte)(_a 16);destination[offset 2] (byte)(_a 8);destination[offset 3] (byte)(_a);destination[offset 4] (byte)(_b 24);destination[offset 5] (byte)(_b 16);destination[offset 6] (byte)(_b 8);destination[offset 7] (byte)(_b);destination[offset 8] (byte)(_c 24);destination[offset 9] (byte)(_c 16);destination[offset 10] (byte)(_c 8);destination[offset 11] (byte)(_c);}/// summary/// Returns a string representation of the value./// /summary/// returnsA string representation of the value./returnspublic override string ToString(){var c new char[24];c[0] BsonUtils.ToHexChar((_a 28) 0x0f);c[1] BsonUtils.ToHexChar((_a 24) 0x0f);c[2] BsonUtils.ToHexChar((_a 20) 0x0f);c[3] BsonUtils.ToHexChar((_a 16) 0x0f);c[4] BsonUtils.ToHexChar((_a 12) 0x0f);c[5] BsonUtils.ToHexChar((_a 8) 0x0f);c[6] BsonUtils.ToHexChar((_a 4) 0x0f);c[7] BsonUtils.ToHexChar(_a 0x0f);c[8] BsonUtils.ToHexChar((_b 28) 0x0f);c[9] BsonUtils.ToHexChar((_b 24) 0x0f);c[10] BsonUtils.ToHexChar((_b 20) 0x0f);c[11] BsonUtils.ToHexChar((_b 16) 0x0f);c[12] BsonUtils.ToHexChar((_b 12) 0x0f);c[13] BsonUtils.ToHexChar((_b 8) 0x0f);c[14] BsonUtils.ToHexChar((_b 4) 0x0f);c[15] BsonUtils.ToHexChar(_b 0x0f);c[16] BsonUtils.ToHexChar((_c 28) 0x0f);c[17] BsonUtils.ToHexChar((_c 24) 0x0f);c[18] BsonUtils.ToHexChar((_c 20) 0x0f);c[19] BsonUtils.ToHexChar((_c 16) 0x0f);c[20] BsonUtils.ToHexChar((_c 12) 0x0f);c[21] BsonUtils.ToHexChar((_c 8) 0x0f);c[22] BsonUtils.ToHexChar((_c 4) 0x0f);c[23] BsonUtils.ToHexChar(_c 0x0f);return new string(c);}// explicit IConvertible implementationTypeCode IConvertible.GetTypeCode(){return TypeCode.Object;}bool IConvertible.ToBoolean(IFormatProvider provider){throw new InvalidCastException();}byte IConvertible.ToByte(IFormatProvider provider){throw new InvalidCastException();}char IConvertible.ToChar(IFormatProvider provider){throw new InvalidCastException();}DateTime IConvertible.ToDateTime(IFormatProvider provider){throw new InvalidCastException();}decimal IConvertible.ToDecimal(IFormatProvider provider){throw new InvalidCastException();}double IConvertible.ToDouble(IFormatProvider provider){throw new InvalidCastException();}short IConvertible.ToInt16(IFormatProvider provider){throw new InvalidCastException();}int IConvertible.ToInt32(IFormatProvider provider){throw new InvalidCastException();}long IConvertible.ToInt64(IFormatProvider provider){throw new InvalidCastException();}sbyte IConvertible.ToSByte(IFormatProvider provider){throw new InvalidCastException();}float IConvertible.ToSingle(IFormatProvider provider){throw new InvalidCastException();}string IConvertible.ToString(IFormatProvider provider){return ToString();}object IConvertible.ToType(Type conversionType, IFormatProvider provider){switch (Type.GetTypeCode(conversionType)){case TypeCode.String:return ((IConvertible)this).ToString(provider);case TypeCode.Object:if (conversionType typeof(object) || conversionType typeof(ObjectId)){return this;}if (conversionType typeof(BsonObjectId)){return new BsonObjectId(this);}if (conversionType typeof(BsonString)){return new BsonString(((IConvertible)this).ToString(provider));}break;}throw new InvalidCastException();}ushort IConvertible.ToUInt16(IFormatProvider provider){throw new InvalidCastException();}uint IConvertible.ToUInt32(IFormatProvider provider){throw new InvalidCastException();}ulong IConvertible.ToUInt64(IFormatProvider provider){throw new InvalidCastException();}}
}