当前位置: 移动技术网 > IT编程>开发语言>c# > 关于C#生成MongoDB中ObjectId的实现方法

关于C#生成MongoDB中ObjectId的实现方法

2019年07月18日  | 移动技术网IT编程  | 我要评论
objectid介绍在mongodb中,文档(document)在集合(collection)中的存储需要一个唯一的_id字段作为主键。这个_id默认使用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类

复制代码 代码如下:

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();
     }
   }


 

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网