0

I need to create a few sequential guids:

00000000-0000-0000-00000000000000001
00000000-0000-0000-00000000000000002
...
00000000-0000-0000-00000000000000011

I need to do this just for a few tests. I do not need thousands of Guids ...

I tried the following but I get a problem when I reach 11.

for (Int32 i = 1; i < 12; i++) {
  Guid guid = new Guid(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (Byte)i);
}

Any way to solve this?

Maybe transforming the int into a string with format and then to Guid?

I really don't know how to solve this ...

Thank You, Miguel

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Miguel Moura
  • 36,732
  • 85
  • 259
  • 481
  • 15
    This is not what guid's are for. – Yosi Dahari Nov 06 '13 at 16:56
  • 3
    `I tried the following but I get a problem when I reach 11.` What problem? – Matt Burland Nov 06 '13 at 16:57
  • Do you need to do this for testing? I wouldn't recommend creating sequential guids of this type for use in any production environment - GUIDs are supposed to be as unique as possible, using several salt values from the host machine to ensure some level of uniqueness – Charleh Nov 06 '13 at 16:57
  • I have seen that in SQL some people use sequential Guids ... But again I am not using it .. I am just running a few tests on an application and I would like to add Guids like that in my dummy data – Miguel Moura Nov 06 '13 at 16:57
  • Yes, I want to replicate those SQL functions in C# so I can create sequential Guids for my dummy data ... In production I am using normal Guids. – Miguel Moura Nov 06 '13 at 16:58
  • A guid is just a 128 bit value anyway, so you should be able to stuff the values into a byte array and pass that in – Charleh Nov 06 '13 at 16:59
  • How? That was what I tried ... Convert an int to Byte array and then to guid ... didn't work ... – Miguel Moura Nov 06 '13 at 17:11

5 Answers5

4

You guid is actually invalid, it should be in the format 00000000-0000-0000-0000-000000000000.

With that in mind, and assuming you are not going to have more than 12 digits changing, you can just do some string formatting:

for (Int32 i = 1; i < 12; i++) 
{
    string s = "00000000-0000-0000-0000-" + i.ToString("D12");
    Guid guid = new Guid(s);
}

Of course if you insist on your original format, then the following line will do that:

string s = "00000000-0000-0000-" + i.ToString("D17");
musefan
  • 47,875
  • 21
  • 135
  • 185
  • Doesn't ToString("F12) produce a float, not hex? Should it not be ToString("X12") ? – SimonGoldstone Nov 06 '13 at 17:07
  • I'm not sure why but I've downvoted this for some reason instead of upvoted but it was an hour ago... if you edit and fix the issue with F then I'll change my vote! – Charleh Nov 06 '13 at 17:58
1

You can use 'shift left' (>>) and 'bitwise and' (&) for this e.g.

short lowest16bit = i & 0xffff;
byte next8bit = (i>>8) & 0xff;

To create a GUID you need 128bits, a regular int is 32bit a long is 64bit.

Using the constructor you used (MSDN):

Guid(int a, short b, short c,
    byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k);

You can create a non-random Guid with 32 non-zero bits from an int using:

int i;
Guid g = new Guid(i, (short)0, (byte)0, (byte)0, (byte)0, ...

You can create a non-random Guid with 64 non-zero bits from a long using:

long l;
Guid g = new Guid((l>>32) & 0xffffffff, (l>>16) & 0xffff, l & 0xffff, (byte)0, ....);

and etc.

Danny Varod
  • 17,324
  • 5
  • 69
  • 111
1

The thing is, the maximum value for an Int32 expressed in hex is only 0x7FFFFFFF so there will be lots of empty room in the guid.

As @Yosi said, this isn't really what they're intended for, but on the basis that this is what you asked for, what about this:

 var guid = "00000000-0000-0000-0000-" + i.ToString("D12")

And to generate a sequence, something like this:

 for (int i = 0; i < 2000; i++)
 {
     var guidStr = "00000000-0000-0000-0000-" + i.ToString("D12");
     var guid = new Guid(guidStr);
     Console.WriteLine(guid);
 }
SimonGoldstone
  • 5,096
  • 3
  • 27
  • 38
  • That does not work ... I tried from 2 to 12 and when I reach 10 I get ....-00000000000a ... I would like ...000000000010 – Miguel Moura Nov 06 '13 at 17:12
  • Ok, then change `X12` to `D12`, like this: `var guid = "00000000-0000-0000-0000-" + i.ToString("D12");` Updated my answer to reflect your requirements. – SimonGoldstone Nov 06 '13 at 17:14
  • 1
    Yes, that's it! I will use 2000 Guids max ... This is just for testing ... I am creating this guids based on the PK which is an int .. that is why ... In production I will not use it ... – Miguel Moura Nov 06 '13 at 17:17
  • Ok, or else you'll have to call them GNuids! – SimonGoldstone Nov 06 '13 at 17:19
  • Converting to string then parsing the string (in the Guid constructor) is a bit redundant when there is already a constructor overload that consumes the int in its binary form, but this will work. – Danny Varod Nov 07 '13 at 00:32
  • I agree totally - *your* solution looks cool, except a bit more complicated and not quite as easy on the eye! I offered this solution up because the code is for testing purposes and not production, so I figured it would be ok. – SimonGoldstone Nov 07 '13 at 01:32
0

I do not recommend using guids as keys. but, you should check out

COMB Guids

and

This SO Question

Using Sql Server syntax, it generates sequential Guids using the following algorithm.

DECLARE @aGuid UNIQUEIDENTIFIER

SET @aGuid = CAST(CAST(NEWID() AS BINARY(10)) 
           + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)
Community
  • 1
  • 1
Charles Bretana
  • 143,358
  • 22
  • 150
  • 216
  • I am not using Guids as PK ... I am using INTS. But on a SQL table which holds files I have an identifier which is a Guid ... For testing I would like that identifier to be sequential ... For sake of simplicity ... Just that ... – Miguel Moura Nov 06 '13 at 17:00
0

This should work to give you a shedload - if you need any more than that then tough!

for (long i = 1; i < long.MaxValue; i++)
{
    var bytes = new byte[16];
    var lngBytes = BitConverter.GetBytes(i);
    Array.Copy(lngBytes, bytes, 8);
    Array.Reverse(bytes);
    var guid = new Guid(bytes);
}

(Actually you'll probably hit an out of memory exception if you use long.MaxValue! So use something sensible!)

Edit:

Ok I just had to do it anyway:

var gids = new List<Guid>();

for (long i = 1; i < 10000; i++)
{ 
     // Skip any values that we don't want
     if ((float)i / 16 % 1 >= 0.625)
     {
         i += 5;
         continue;
     }

     var bytes = new byte[16];
     var lngBytes = BitConverter.GetBytes(i);
     Array.Copy(lngBytes, bytes, 8);
     Array.Reverse(bytes);
     gids.Add(new Guid(bytes));
 }

A nice mathematical way of doing it.. :) (argh it actually dies after 100 iterations, but I'm sure I just need to tweak the skip formula!)

Charleh
  • 13,749
  • 3
  • 37
  • 57
  • Yes, similar to what I add ... But I forgot the 16 in new Byte[16] ... But again you will get -00000000000a as soon you get to 10 ... And I would like to get -000000000010 ... – Miguel Moura Nov 06 '13 at 17:15
  • No problem with the maximum value ... I will not need more then 2000 guids for testing. – Miguel Moura Nov 06 '13 at 17:15
  • Ah I see you want to generate a sequential STRING version of a guid...give me a second! – Charleh Nov 06 '13 at 17:15