ObjectId Introduction
In MongoDB, a unique _ id field is required to store documents in collections as the primary key. By default, ObjectId is used to define the _ id, because the definition of ObjectId is short enough to maintain uniqueness as much as possible and can be quickly generated.
ObjectId is a 12 Bytes BSON type, which contains:
1.4 Bytes: the number of seconds since the epoch time
2.3 Bytes machine Descriptor
3.2 Bytes process ID
4.3 Bytes Random Number
It can be seen from the definition that the same ObjectId may be generated under the same process ID condition on different machines within the same second.
At the same time, it can be determined according to the definition that under the given conditions, ObjectId itself can describe the generated time sequence.
The storage of ObjectId uses a Byte array, and its display needs to convert the Byte array to a string for display. Therefore, the ObjectId we usually see is similar:
ObjectId ("507f191e810c19729de860ea ")
C # define the ObjectId class
Copy codeThe Code is as follows: 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
{
Obtain {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 Generator
Copy codeThe Code is as follows: 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 ++;
}
}
}
Example
Copy codeThe Code is as follows: 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 ();
}
}