tag:blogger.com,1999:blog-13221527.post2999122333442528546..comments2023-10-26T05:42:47.148-04:00Comments on Development tips: Generate Sequential GUIDs for SQL Server 2005 in C#Dennis Gorelikhttp://www.blogger.com/profile/17700219093521377626noreply@blogger.comBlogger9125tag:blogger.com,1999:blog-13221527.post-465141230036008262015-02-11T10:27:13.147-05:002015-02-11T10:27:13.147-05:00Code Correction:
public static Sequential...Code Correction:<br /><br /> public static SequentialGuid operator ++(SequentialGuid sequentialGuid)<br /> {<br /> byte[] bytes = sequentialGuid._currentGuid.ToByteArray();<br /> for (int mapIndex = 0; mapIndex < 16; mapIndex++)<br /> {<br /> int bytesIndex = SqlOrderMap[mapIndex];<br /> bytes[bytesIndex]++;<br /> if (bytes[bytesIndex] != 0)<br /> {<br /> break; // No need to increment more significant bytes<br /> }<br /> }<br /><br /> return new SequentialGuid(new Guid(bytes));<br /> }<br />Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-13221527.post-14765192342494474812015-02-11T10:05:52.756-05:002015-02-11T10:05:52.756-05:00Bug:
The post increment++ does not work properly. ...Bug:<br />The post increment++ does not work properly. The following source source prints the same output for post-increment and pre-increment.<br /><br /> var seqGuid = new SequentialGuid(Guid.Parse("145F7098-1A68-466E-B7A5-2D72D3798B7D"));<br /><br /> Console.WriteLine("---------------------------------------------------");<br /> Console.WriteLine(seqGuid);<br /> var guid1 = seqGuid++;<br /> Console.WriteLine(guid1);<br /><br /> Console.WriteLine(seqGuid);<br /> var guid2 = seqGuid++;<br /> Console.WriteLine(guid2);<br /><br /> Console.WriteLine(seqGuid);<br /> var guid3 = seqGuid++;<br /> Console.WriteLine(guid3);<br /><br /><br /> seqGuid = new SequentialGuid(Guid.Parse("145F7098-1A68-466E-B7A5-2D72D3798B7D"));<br /><br /> Console.WriteLine("---------------------------------------------------");<br /> Console.WriteLine(seqGuid);<br /> guid1 = ++seqGuid;<br /> Console.WriteLine(guid1);<br /><br /> Console.WriteLine(seqGuid);<br /> guid2 = ++seqGuid;<br /> Console.WriteLine(guid2);<br /><br /> Console.WriteLine(seqGuid);<br /> guid3 = ++seqGuid;<br /> Console.WriteLine(guid3);Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-13221527.post-91510770181577572662014-02-17T09:58:55.055-05:002014-02-17T09:58:55.055-05:00Mike, I'm glad it helped.
However even better...Mike, I'm glad it helped.<br /><br />However even better solution would be not to use GUID as an identity key (or as a primary key) at all.<br />I figured it out somewhere in between I wrote this blog post (6 years ago) and now.<br /><br />Int key works so much better:<br />- Less data.<br />- Shorter and faster indexes.<br />- Identical increment operations in SQL Server and C#.<br /><br />The only real advantage GUID has is that it's hard to guess. But as soon as you start using sequential key generation that advantage disappears.<br /><br />What is your reason to use GUID?Dennis Gorelikhttps://www.blogger.com/profile/17700219093521377626noreply@blogger.comtag:blogger.com,1999:blog-13221527.post-51053394775937651102014-02-17T05:36:49.298-05:002014-02-17T05:36:49.298-05:00This is excellent code, and has just solved a huge...This is excellent code, and has just solved a huge bulk-insert performance problem we were having.<br /><br />However, I really don't want records in my database with GUID values like 01000000-0000-0000-0000-000000000000 <br /><br />So, when I use your class, I start it off with a random GUID, and let subsequent GUIDs get calculated from there:<br /><br />SequentialGuid guid = new SequentialGuid(Guid.NewGuid());<br />guid++;<br /><br />MikeGledhillhttps://www.blogger.com/profile/00909359069387630986noreply@blogger.comtag:blogger.com,1999:blog-13221527.post-16716109357071256742009-11-23T08:58:10.168-05:002009-11-23T08:58:10.168-05:00Thanks for your answer Dennis, yes that makes sens...Thanks for your answer Dennis, yes that makes sense I just wasn't sure which way it went if the sort was based off the most significant or least significant bytes there until your comment cleared it up for me.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-13221527.post-52624247841160416782009-11-20T15:44:16.718-05:002009-11-20T15:44:16.718-05:00dotnetchris: the more significant byte is the stro...dotnetchris: the more significant byte is the stronger it affects overall sorting order.<br /><br />For example, if you compare<br />100 with 010 then 100 is bigger, because the most significant [leftmost] bit in "100" is "1", which is bigger than the most significant bit in "010" which is "0".<br /><br />It seems than in SQL server the most significant byte is not on the left, but on position #10.<br /><br />Does it help?Dennis Gorelikhttps://www.blogger.com/profile/17700219093521377626noreply@blogger.comtag:blogger.com,1999:blog-13221527.post-71195654369839363422009-11-20T15:30:11.015-05:002009-11-20T15:30:11.015-05:00Dennis,
Could you please elaborate on your discus...Dennis,<br /><br />Could you please elaborate on your discussion of the most and least significant bits. Both on how you determined the significance of the bits and then what the implications are of changing the highest vs the lowest.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-13221527.post-59569891440011112122008-07-04T13:10:00.000-04:002008-07-04T13:10:00.000-04:00Magnus,I see at least two possible ways to solve "...Magnus,<BR/><BR/>I see at least two possible ways to solve "Generate Sequential GUID across multiple machines":<BR/><BR/>Solution #1:<BR/>Create web service that all your machines would call. This service would generate unique sequential GUIDs for all other machines.<BR/><BR/>Solution #2:<BR/>Put DateTime.Now into appropriate bytes of GUID (your idea). Select these GUID bytes in such a way that GUIDs will be sorted by using these datetime bytes first and would sort by other bytes later.<BR/>You may put machine number into last (the least significant) byte of GUID, so machine number would not affect sorting, but it still would ensure that GUIDs generated on different machines are unique.<BR/>Use "middle" GUID bytes to put sequential number in case if you need to generate more than one GUID during the same millisecond.Dennis Gorelikhttps://www.blogger.com/profile/17700219093521377626noreply@blogger.comtag:blogger.com,1999:blog-13221527.post-75186279859011962022008-06-19T06:47:00.000-04:002008-06-19T06:47:00.000-04:00Thank you for your article.In my case I run code o...Thank you for your article.<BR/><BR/>In my case I run code on several different machines, and thus is not able to use a single shared SequentialGuid object. Is there a way to call the constructor with a value depending on e.g. DateTime.Now?<BR/><BR/>In other words, I need a method to call anywhere from any server and still get i sequential guid larger than those generated before.<BR/><BR/>Regards<BR/>MagnusMEMarkhttps://www.blogger.com/profile/06033573917557524827noreply@blogger.com