Create a Guid from an int

倖福魔咒の 提交于 2019-12-21 04:07:09

问题


Given an int, how can you create the same Guid repeatedly?

Edit:
I'm integrating two systems, one uses ints as a primary key, the other recognises an object by it's Guid. Because of this, I need to be able to recreate the same Guid for a given int so that the second system can recognise the entities coming from the first.


回答1:


If you create a Guid based on an integer it will no longer be a globally unique identifier.

Having said that you can use the constructor that takes an integer and some other parameters:

int a = 5;
Guid guid = new Guid(a, 0, 0, new byte[8]);

Not really advisable...




回答2:


This is the perfect use for a Version 3 or a Version 5 guid.

There are five kinds of guids:

  • 1: time based version (UuidCreateSequential)
  • 2: DCE Security version, with embedded POSIX UIDs
  • 3: Name-based version that uses MD5 hashing
  • 4: Randomly or pseudo-randomly generated version (UuidCreate)
  • 5: Name-based version that uses SHA-1 hashing

Version 3 and Version 5 are designed to have an arbitrary name always map to the same guid.

The idea is to take an arbitrary "name" and a "namespace", hash them, and the hash is carefully stored in a guid structure, conceptually:

"CustomersTable" + "1"  -> sha1() -> Guid
"CustomersTable" + "2"  -> sha1() -> Guid

You avoid collisions of the the same "name" by prefixing with the "namespace":

"InvoicesTable" + "1"   -> sha1() -> Guid
"InvoicesTable" + "2"   -> sha1() -> Guid

Except rather than the "namespace" being a string, it is specified that it be a guid:

Namespace_Customer = '{277D668B-264A-433E-9EEB-867C02C6D48D}';
Namespace_Invoice =  '{D8024CFB-D6F8-4DB2-9135-96FD0A7B97AB}';

The RFC gives four pre-defined namespace uuids:

NameSpace_DNS =  '{6ba7b810-9dad-11d1-80b4-00c04fd430c8}';
NameSpace_URL =  '{6ba7b811-9dad-11d1-80b4-00c04fd430c8}';
NameSpace_OID =  '{6ba7b812-9dad-11d1-80b4-00c04fd430c8}';
NameSpace_X500 = '{6ba7b814-9dad-11d1-80b4-00c04fd430c8}';

The rfc describes how to put the 16 bytes of your hash into the guid structure. If the first 16 bytes of your hash are:

hex: 00010203040506070809101112131415

They are mapped into the uuid structure:

                timeLow = 00 01 02 03
                timeMid = 04 05
     timeHighAndVersion = ((06 07) & 0x0FFF) | (0x5000)  //high 4-bits are version, 5=SHA1, 3=MD5
  clockSeqHiAndReserved = (08 & 0x3F) | 0xD0    //set high bits to 10
            clockSeqLow = 09
                   node = 10 11 12 13 14 15

Running your customers and invoices through my NameToGuid function gives:

NameToGUIDA(Namespace_Customer, "1") =  {7E378BDB-5BB1-5EBF-9C63-E00AC1AEEDB7}
NameToGUIDA(Namespace_Customer, "2") =  {830F19D8-D5DC-5321-8CF9-D708660BE473}
NameToGUIDA(Namespace_Customer, "10") = {C052F6ED-0334-5827-B077-7F4C28B78223}

NameToGUIDA(Namespace_Invoice, "1") =   {BB5408DA-B99C-5816-B144-A63CC02BB21C}
NameToGUIDA(Namespace_Invoice, "2") =   {73DDD3B3-1139-50C8-9B0D-067145611346}
NameToGUIDA(Namespace_Invoice, "10") =  {AE1799A8-620F-55DB-AC85-D7056B70AFB5}



回答3:


If you want the guid to consist of just the int then:

int x = 5;
string padded = x.ToString().PadLeft(32,'0');
var intGuid = new Guid(padded);

intGuid.ToString(); // 00000000-0000-0000-0000-000000000005



回答4:


You could convert an int64 to a byte[] and use the constructor overload to do it:

var guid = new Guid(byteArray);

Edit -- oops.. It's based off of 128 bits, not 64.. If you had a custom type, MyBigInt (a 128-bit int), then you could do it the aforementioned way.



来源:https://stackoverflow.com/questions/3303829/create-a-guid-from-an-int

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!