├── .gitattributes
├── .gitignore
├── README.md
├── SequentialGuid.Demo
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── SequentialGuid.Demo.csproj
├── SequentialGuidDemoForm.Designer.cs
├── SequentialGuidDemoForm.cs
└── SequentialGuidDemoForm.resx
├── SequentialGuid.sln
└── SequentialGuid
├── Classes
└── SequentialGuid.cs
├── Enums
└── SequentialGuidType.cs
├── Properties
└── AssemblyInfo.cs
└── SequentialGuid.csproj
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set default behaviour to automatically normalize line endings.
2 | * text=auto
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 |
18 | # MSTest test Results
19 | [Tt]est[Rr]esult*/
20 | [Bb]uild[Ll]og.*
21 |
22 | *_i.c
23 | *_p.c
24 | *.ilk
25 | *.meta
26 | *.obj
27 | *.pch
28 | *.pdb
29 | *.pgc
30 | *.pgd
31 | *.rsp
32 | *.sbr
33 | *.tlb
34 | *.tli
35 | *.tlh
36 | *.tmp
37 | *.tmp_proj
38 | *.log
39 | *.vspscc
40 | *.vssscc
41 | .builds
42 | *.pidb
43 | *.log
44 | *.scc
45 |
46 | # Visual C++ cache files
47 | ipch/
48 | *.aps
49 | *.ncb
50 | *.opensdf
51 | *.sdf
52 | *.cachefile
53 |
54 | # Visual Studio profiler
55 | *.psess
56 | *.vsp
57 | *.vspx
58 |
59 | # Guidance Automation Toolkit
60 | *.gpState
61 |
62 | # ReSharper is a .NET coding add-in
63 | _ReSharper*/
64 | *.[Rr]e[Ss]harper
65 |
66 | # TeamCity is a build add-in
67 | _TeamCity*
68 |
69 | # DotCover is a Code Coverage Tool
70 | *.dotCover
71 |
72 | # NCrunch
73 | *.ncrunch*
74 | .*crunch*.local.xml
75 |
76 | # Installshield output folder
77 | [Ee]xpress/
78 |
79 | # DocProject is a documentation generator add-in
80 | DocProject/buildhelp/
81 | DocProject/Help/*.HxT
82 | DocProject/Help/*.HxC
83 | DocProject/Help/*.hhc
84 | DocProject/Help/*.hhk
85 | DocProject/Help/*.hhp
86 | DocProject/Help/Html2
87 | DocProject/Help/html
88 |
89 | # Click-Once directory
90 | publish/
91 |
92 | # Publish Web Output
93 | *.Publish.xml
94 | *.pubxml
95 |
96 | # NuGet Packages Directory
97 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
98 | #packages/
99 |
100 | # Windows Azure Build Output
101 | csx
102 | *.build.csdef
103 |
104 | # Windows Store app package directory
105 | AppPackages/
106 |
107 | # Others
108 | sql/
109 | *.Cache
110 | ClientBin/
111 | [Ss]tyle[Cc]op.*
112 | ~$*
113 | *~
114 | *.dbmdl
115 | *.[Pp]ublish.xml
116 | *.pfx
117 | *.publishsettings
118 |
119 | # RIA/Silverlight projects
120 | Generated_Code/
121 |
122 | # Backup & report files from converting an old project file to a newer
123 | # Visual Studio version. Backup files are not needed, because we have git ;-)
124 | _UpgradeReport_Files/
125 | Backup*/
126 | UpgradeLog*.XML
127 | UpgradeLog*.htm
128 |
129 | # SQL Server files
130 | App_Data/*.mdf
131 | App_Data/*.ldf
132 |
133 |
134 | #LightSwitch generated files
135 | GeneratedArtifacts/
136 | _Pvt_Extensions/
137 | ModelManifest.xml
138 |
139 | # =========================
140 | # Windows detritus
141 | # =========================
142 |
143 | # Windows image file caches
144 | Thumbs.db
145 | ehthumbs.db
146 |
147 | # Folder config file
148 | Desktop.ini
149 |
150 | # Recycle Bin used on file shares
151 | $RECYCLE.BIN/
152 |
153 | # Mac desktop service store files
154 | .DS_Store
155 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SequentialGuid
2 | ==============
3 |
4 | Author: Jeremy H. Todd (http://jeremytodd.org/)
5 | License: Public domain
6 |
7 | Description
8 | -----------
9 |
10 | This is an example project to demonstrate the creation of sequential GUID values for use as primary keys in database tables under various database types.
11 | It is intended to accompany my article [GUIDs as fast primary keys under multiple databases](http://www.codeproject.com/Articles/388157/GUIDs-as-fast-primary-keys-under-multiple-database).
12 |
13 | Contents
14 | --------
15 |
16 | A Visual Studio solution containing two projects:
17 |
18 | * SequentialGuid - A small library containing the types and methods to generate sequential GUIDs using the method outlined in the article.
19 | * SequentialGuid.Demo - A WinForms application demonstrating the generation and use of sequential GUIDs.
20 |
--------------------------------------------------------------------------------
/SequentialGuid.Demo/Program.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright © Jeremy H. Todd 2011
4 | //
5 | //-----------------------------------------------------------------------
6 | namespace SequentialGuid.Demo
7 | {
8 | using System;
9 | using System.Collections.Generic;
10 | using System.Linq;
11 | using System.Windows.Forms;
12 |
13 | ///
14 | /// The entry point of the application.
15 | ///
16 | public static class Program
17 | {
18 | ///
19 | /// The main entry point for the application.
20 | ///
21 | [STAThread]
22 | public static void Main()
23 | {
24 | Application.EnableVisualStyles();
25 | Application.SetCompatibleTextRenderingDefault(false);
26 | Application.Run(new SequentialGuidDemoForm());
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/SequentialGuid.Demo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright © Jeremy H. Todd 2011
4 | //
5 | //-----------------------------------------------------------------------
6 | using System.Reflection;
7 | using System.Runtime.CompilerServices;
8 | using System.Runtime.InteropServices;
9 |
10 | // General Information about an assembly is controlled through the following
11 | // set of attributes. Change these attribute values to modify the information
12 | // associated with an assembly.
13 | [assembly: AssemblyTitle("SequentialGuid.Demo")]
14 | [assembly: AssemblyDescription("A demonstration form for sequential GUIDs.")]
15 | [assembly: AssemblyConfiguration("")]
16 | [assembly: AssemblyCompany("Jeremy H. Todd")]
17 | [assembly: AssemblyProduct("SequentialGuid.Demo")]
18 | [assembly: AssemblyCopyright("Copyright © Jeremy H. Todd 2012")]
19 | [assembly: AssemblyTrademark("")]
20 | [assembly: AssemblyCulture("")]
21 |
22 | // Setting ComVisible to false makes the types in this assembly not visible
23 | // to COM components. If you need to access a type in this assembly from
24 | // COM, set the ComVisible attribute to true on that type.
25 | [assembly: ComVisible(false)]
26 |
27 | // The following GUID is for the ID of the typelib if this project is exposed to COM
28 | [assembly: Guid("6f6df617-95c1-44eb-b59d-14527f2e85e9")]
29 |
30 | // Version information for an assembly consists of the following four values:
31 | //
32 | // Major Version
33 | // Minor Version
34 | // Build Number
35 | // Revision
36 | //
37 | // You can specify all the values or you can default the Build and Revision Numbers
38 | // by using the '*' as shown below:
39 | // [assembly: AssemblyVersion("1.0.*")]
40 | [assembly: AssemblyVersion("1.0.0.0")]
41 | [assembly: AssemblyFileVersion("1.0.0.0")]
42 |
--------------------------------------------------------------------------------
/SequentialGuid.Demo/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18034
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SequentialGuid.Demo.Properties {
12 |
13 |
14 | ///
15 | /// A strongly-typed resource class, for looking up localized strings, etc.
16 | ///
17 | // This class was auto-generated by the StronglyTypedResourceBuilder
18 | // class via a tool like ResGen or Visual Studio.
19 | // To add or remove a member, edit your .ResX file then rerun ResGen
20 | // with the /str option, or rebuild your VS project.
21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
24 | internal class Resources {
25 |
26 | private static global::System.Resources.ResourceManager resourceMan;
27 |
28 | private static global::System.Globalization.CultureInfo resourceCulture;
29 |
30 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
31 | internal Resources() {
32 | }
33 |
34 | ///
35 | /// Returns the cached ResourceManager instance used by this class.
36 | ///
37 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
38 | internal static global::System.Resources.ResourceManager ResourceManager {
39 | get {
40 | if ((resourceMan == null)) {
41 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SequentialGuid.Demo.Properties.Resources", typeof(Resources).Assembly);
42 | resourceMan = temp;
43 | }
44 | return resourceMan;
45 | }
46 | }
47 |
48 | ///
49 | /// Overrides the current thread's CurrentUICulture property for all
50 | /// resource lookups using this strongly typed resource class.
51 | ///
52 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
53 | internal static global::System.Globalization.CultureInfo Culture {
54 | get {
55 | return resourceCulture;
56 | }
57 | set {
58 | resourceCulture = value;
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/SequentialGuid.Demo/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/SequentialGuid.Demo/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18034
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SequentialGuid.Demo.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings) (global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/SequentialGuid.Demo/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SequentialGuid.Demo/SequentialGuid.Demo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {C9B2DD84-3303-47CE-9F7A-85AE7C7699D9}
8 | WinExe
9 | Properties
10 | SequentialGuid.Demo
11 | SequentialGuid.Demo
12 | v4.0
13 | 512
14 | 1
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | True
26 | False
27 | False
28 | False
29 | False
30 | False
31 | True
32 | True
33 | True
34 | True
35 | True
36 | True
37 | True
38 | True
39 | True
40 | True
41 | True
42 | True
43 | True
44 | True
45 | True
46 | False
47 | False
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | True
56 | False
57 | Full
58 | DoNotBuild
59 | 2
60 |
61 |
62 | AnyCPU
63 | pdbonly
64 | true
65 | bin\Release\
66 | TRACE
67 | prompt
68 | 4
69 | True
70 | True
71 | True
72 | False
73 | False
74 | False
75 | True
76 | True
77 | False
78 | False
79 | False
80 | True
81 | True
82 | False
83 | False
84 | False
85 | True
86 | False
87 | False
88 | True
89 | True
90 | False
91 | True
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | True
100 | False
101 | Preconditions
102 | Build
103 | 0
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | Form
113 |
114 |
115 | SequentialGuidDemoForm.cs
116 |
117 |
118 |
119 |
120 | SequentialGuidDemoForm.cs
121 |
122 |
123 | ResXFileCodeGenerator
124 | Resources.Designer.cs
125 | Designer
126 |
127 |
128 | True
129 | Resources.resx
130 |
131 |
132 | SettingsSingleFileGenerator
133 | Settings.Designer.cs
134 |
135 |
136 | True
137 | Settings.settings
138 | True
139 |
140 |
141 |
142 |
143 | {52ee6d7a-286d-44d1-b189-f1f027808e61}
144 | SequentialGuid
145 |
146 |
147 |
148 |
155 |
--------------------------------------------------------------------------------
/SequentialGuid.Demo/SequentialGuidDemoForm.Designer.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright © Jeremy H. Todd 2011
4 | //
5 | //-----------------------------------------------------------------------
6 | namespace SequentialGuid.Demo
7 | {
8 | ///
9 | /// The demonstration form for sequential GUIDs.
10 | ///
11 | public partial class SequentialGuidDemoForm
12 | {
13 | ///
14 | /// Required designer variable.
15 | ///
16 | private System.ComponentModel.IContainer components = null;
17 |
18 | /// The TextBox that contains the results of the GUID generation.
19 | private System.Windows.Forms.RichTextBox resultsTextBox;
20 |
21 | /// The button that begins GUID generation.
22 | private System.Windows.Forms.Button generateButton;
23 |
24 | /// The ComboBox specifying the GUID generation method.
25 | private System.Windows.Forms.ComboBox methodComboBox;
26 |
27 | /// The TextBox that contains the comments.
28 | private System.Windows.Forms.TextBox commentsTextBox;
29 |
30 | /// The label for the method ComboBox.
31 | private System.Windows.Forms.Label methodLabel;
32 |
33 | ///
34 | /// Clean up any resources being used.
35 | ///
36 | /// true if managed resources should be disposed; otherwise, false.
37 | protected override void Dispose(bool disposing)
38 | {
39 | if (disposing && (this.components != null))
40 | {
41 | this.components.Dispose();
42 | }
43 |
44 | base.Dispose(disposing);
45 | }
46 |
47 | #region Windows Form Designer generated code
48 |
49 | ///
50 | /// Required method for Designer support - do not modify
51 | /// the contents of this method with the code editor.
52 | ///
53 | private void InitializeComponent()
54 | {
55 | this.resultsTextBox = new System.Windows.Forms.RichTextBox();
56 | this.generateButton = new System.Windows.Forms.Button();
57 | this.methodComboBox = new System.Windows.Forms.ComboBox();
58 | this.commentsTextBox = new System.Windows.Forms.TextBox();
59 | this.methodLabel = new System.Windows.Forms.Label();
60 | this.SuspendLayout();
61 | //
62 | // resultsTextBox
63 | //
64 | this.resultsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
65 | | System.Windows.Forms.AnchorStyles.Left)
66 | | System.Windows.Forms.AnchorStyles.Right)));
67 | this.resultsTextBox.BackColor = System.Drawing.Color.White;
68 | this.resultsTextBox.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
69 | this.resultsTextBox.ForeColor = System.Drawing.Color.Black;
70 | this.resultsTextBox.Location = new System.Drawing.Point(152, 12);
71 | this.resultsTextBox.Name = "resultsTextBox";
72 | this.resultsTextBox.ReadOnly = true;
73 | this.resultsTextBox.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical;
74 | this.resultsTextBox.Size = new System.Drawing.Size(546, 297);
75 | this.resultsTextBox.TabIndex = 3;
76 | this.resultsTextBox.Text = string.Empty;
77 | //
78 | // generateButton
79 | //
80 | this.generateButton.Location = new System.Drawing.Point(15, 72);
81 | this.generateButton.Name = "generateButton";
82 | this.generateButton.Size = new System.Drawing.Size(121, 23);
83 | this.generateButton.TabIndex = 2;
84 | this.generateButton.Text = "Generate";
85 | this.generateButton.UseVisualStyleBackColor = true;
86 | this.generateButton.Click += new System.EventHandler(this.GenerateButton_Click);
87 | //
88 | // methodComboBox
89 | //
90 | this.methodComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
91 | this.methodComboBox.FormattingEnabled = true;
92 | this.methodComboBox.Location = new System.Drawing.Point(15, 32);
93 | this.methodComboBox.Name = "methodComboBox";
94 | this.methodComboBox.Size = new System.Drawing.Size(121, 21);
95 | this.methodComboBox.TabIndex = 1;
96 | this.methodComboBox.SelectedIndexChanged += new System.EventHandler(this.MethodComboBox_SelectedIndexChanged);
97 | //
98 | // commentsTextBox
99 | //
100 | this.commentsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
101 | | System.Windows.Forms.AnchorStyles.Right)));
102 | this.commentsTextBox.BackColor = System.Drawing.Color.White;
103 | this.commentsTextBox.ForeColor = System.Drawing.Color.Black;
104 | this.commentsTextBox.Location = new System.Drawing.Point(152, 315);
105 | this.commentsTextBox.Multiline = true;
106 | this.commentsTextBox.Name = "commentsTextBox";
107 | this.commentsTextBox.ReadOnly = true;
108 | this.commentsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
109 | this.commentsTextBox.Size = new System.Drawing.Size(546, 120);
110 | this.commentsTextBox.TabIndex = 4;
111 | //
112 | // methodLabel
113 | //
114 | this.methodLabel.AutoSize = true;
115 | this.methodLabel.Location = new System.Drawing.Point(12, 16);
116 | this.methodLabel.Name = "methodLabel";
117 | this.methodLabel.Size = new System.Drawing.Size(79, 13);
118 | this.methodLabel.TabIndex = 0;
119 | this.methodLabel.Text = "Select Method:";
120 | //
121 | // SequentialGuidDemoForm
122 | //
123 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
124 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
125 | this.ClientSize = new System.Drawing.Size(710, 447);
126 | this.Controls.Add(this.methodLabel);
127 | this.Controls.Add(this.commentsTextBox);
128 | this.Controls.Add(this.methodComboBox);
129 | this.Controls.Add(this.generateButton);
130 | this.Controls.Add(this.resultsTextBox);
131 | this.Name = "SequentialGuidDemoForm";
132 | this.Text = "SequentialGuid Demonstration Form";
133 | this.ResumeLayout(false);
134 | this.PerformLayout();
135 | }
136 |
137 | #endregion
138 | }
139 | }
--------------------------------------------------------------------------------
/SequentialGuid.Demo/SequentialGuidDemoForm.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright © Jeremy H. Todd 2011
4 | //
5 | //-----------------------------------------------------------------------
6 | namespace SequentialGuid.Demo
7 | {
8 | using System;
9 | using System.Text;
10 | using System.Windows.Forms;
11 |
12 | ///
13 | /// The demonstration form for sequential GUIDs.
14 | ///
15 | public partial class SequentialGuidDemoForm : Form
16 | {
17 | ///
18 | /// Initializes a new instance of the class.
19 | ///
20 | public SequentialGuidDemoForm()
21 | {
22 | this.InitializeComponent();
23 |
24 | // Load the enumeration values into the combo box
25 | foreach (var value in Enum.GetValues(typeof(SequentialGuidType)))
26 | {
27 | this.methodComboBox.Items.Add(value);
28 | }
29 |
30 | this.methodComboBox.SelectedIndex = 0;
31 | }
32 |
33 | ///
34 | /// Updates the form when the user changes the value of the Method ComboBox.
35 | ///
36 | /// The Method ComboBox.
37 | /// Additional information related to the event.
38 | private void MethodComboBox_SelectedIndexChanged(object sender, EventArgs e)
39 | {
40 | string comments = string.Empty;
41 |
42 | switch ((SequentialGuidType)this.methodComboBox.SelectedItem)
43 | {
44 | case SequentialGuidType.SequentialAsBinary:
45 | comments = "GUIDs will be generated using the SequentialAsBinary method, which is appropriate " +
46 | "if the values are going to be written to a binary field, such as a raw(16) column " +
47 | "under Oracle, or a binary(16) column under MySQL. These GUIDs are formatted by " +
48 | "invoking Guid.ToByteArray() on the GUID value, then writing the results to a hex " +
49 | "string. This is most likely the way ORM frameworks would generate INSERT statements " +
50 | "for writing to a binary field. The sequential portion of the generated GUIDs will be " +
51 | "highlighted in red.";
52 | break;
53 |
54 | case SequentialGuidType.SequentialAsString:
55 | comments = "GUIDs will be generated using the SequentialAsString method, which is appropriate " +
56 | "if the values are going to be written to a string-based column (which would include " +
57 | "char(36) columns under MySQL and other database, or a uuid column under PostgreSQL). " +
58 | "These GUIDs are formatted by invoking Guid.ToString() on the GUID value. Why do " +
59 | "string-based columns need a different format from binary columns? Because a quirk " +
60 | "of the way the .NET Framework handles GUIDs introduces endianness issues that need " +
61 | "to be corrected when writing to a string. The sequential portion of the generated " +
62 | "GUIDs will be highlighted in red.";
63 | break;
64 |
65 | case SequentialGuidType.SequentialAtEnd:
66 | comments = "GUIDs will be generated using the SequentialAtEnd method, which is pretty much " +
67 | "only appropriate for a Microsoft SQL Server uniqueidentifier column. This special " +
68 | "format is necessary because SQL Server uses an unusual ordering scheme for GUID " +
69 | "values, basing the order on the last six bytes instead of starting from the beginning." +
70 | "The sequential portion of the generated GUIDs will be highlighted in red.";
71 | break;
72 | }
73 |
74 | this.resultsTextBox.Clear();
75 | this.commentsTextBox.Text = comments;
76 | }
77 |
78 | ///
79 | /// Generates the GUIDs and displays them in the form.
80 | ///
81 | /// The Generate button.
82 | /// Additional information related to the event.
83 | private void GenerateButton_Click(object sender, EventArgs e)
84 | {
85 | int count = 100;
86 | SequentialGuidType method = (SequentialGuidType)this.methodComboBox.SelectedItem;
87 |
88 | // Initialize the RTF text to enable color highlighting
89 | StringBuilder text = new StringBuilder();
90 | text.Append("{\\rtf1\\ansi\\deff0\n{\\colortbl;\\red0\\green0\\blue0;\\red128\\green0\\blue0;}\n");
91 |
92 | for (int i = 0; i < count; i++)
93 | {
94 | Guid guid = SequentialGuid.Create(method);
95 | string output = string.Empty;
96 |
97 | switch (method)
98 | {
99 | case SequentialGuidType.SequentialAsBinary:
100 | byte[] bytes = guid.ToByteArray();
101 |
102 | foreach (byte b in bytes)
103 | {
104 | output += string.Format("{0:x2}", b);
105 | }
106 |
107 | output = "\\cf2\n" + output.Substring(0, 12) + "\n\\cf1\n" + output.Substring(12) + "\n\\line\n";
108 | break;
109 |
110 | case SequentialGuidType.SequentialAsString:
111 | output = guid.ToString();
112 | output = "\\cf2\n" + output.Substring(0, 13) + "\n\\cf1\n" + output.Substring(13) + "\n\\line\n";
113 | break;
114 |
115 | case SequentialGuidType.SequentialAtEnd:
116 | output = guid.ToString();
117 | output = "\\cf1\n" + output.Substring(0, 24) + "\n\\cf2\n" + output.Substring(24) + "\n\\line\n";
118 | break;
119 |
120 | default:
121 | output = guid.ToString();
122 | break;
123 | }
124 |
125 | text.Append(output);
126 | System.Threading.Thread.Sleep(1);
127 | }
128 |
129 | this.resultsTextBox.Rtf = text.ToString();
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/SequentialGuid.Demo/SequentialGuidDemoForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/SequentialGuid.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SequentialGuid.Demo", "SequentialGuid.Demo\SequentialGuid.Demo.csproj", "{C9B2DD84-3303-47CE-9F7A-85AE7C7699D9}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SequentialGuid", "SequentialGuid\SequentialGuid.csproj", "{52EE6D7A-286D-44D1-B189-F1F027808E61}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {C9B2DD84-3303-47CE-9F7A-85AE7C7699D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {C9B2DD84-3303-47CE-9F7A-85AE7C7699D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {C9B2DD84-3303-47CE-9F7A-85AE7C7699D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {C9B2DD84-3303-47CE-9F7A-85AE7C7699D9}.Release|Any CPU.Build.0 = Release|Any CPU
18 | {52EE6D7A-286D-44D1-B189-F1F027808E61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {52EE6D7A-286D-44D1-B189-F1F027808E61}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {52EE6D7A-286D-44D1-B189-F1F027808E61}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {52EE6D7A-286D-44D1-B189-F1F027808E61}.Release|Any CPU.Build.0 = Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | EndGlobal
27 |
--------------------------------------------------------------------------------
/SequentialGuid/Classes/SequentialGuid.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright © Jeremy H. Todd 2011
4 | //
5 | //-----------------------------------------------------------------------
6 | namespace SequentialGuid
7 | {
8 | using System;
9 | using System.Diagnostics.Contracts;
10 | using System.Security.Cryptography;
11 |
12 | ///
13 | /// Contains methods for creating sequential GUID values.
14 | ///
15 | public static partial class SequentialGuid
16 | {
17 | #region Static Fields
18 | ///
19 | /// Provides cryptographically strong random data for GUID creation.
20 | ///
21 | private static readonly RNGCryptoServiceProvider RandomGenerator = new RNGCryptoServiceProvider();
22 | #endregion
23 |
24 | ///
25 | /// Returns a new GUID value which is sequentially ordered when formatted as
26 | /// a string, a byte array, or ordered by the least significant six bytes of the
27 | /// Data4 block, as specified by .
28 | ///
29 | ///
30 | /// Specifies the type of sequential GUID (i.e. whether sequential as a string,
31 | /// as a byte array, or according to the Data4 block. This can affect
32 | /// performance under various database types; see below.
33 | ///
34 | ///
35 | /// A structure whose value is created by replacing
36 | /// certain randomly-generated bytes with a sequential timestamp.
37 | ///
38 | ///
39 | ///
40 | /// This method creates a new GUID value which combines a random component
41 | /// with the current timestamp, also known as a COMB. The general concept
42 | /// is outlined in Jimmy Nilsson's article "The Cost of GUIDs as Primary Keys",
43 | /// and involves replacing either the least significant or most significant
44 | /// six bytes of the GUID with the current timestamp. This reduces the
45 | /// random component of the GUID from 16 bytes to 10 bytes, but this is
46 | /// still sufficient to prevent a collision under most real-world circumstances.
47 | ///
48 | ///
49 | /// The purpose of sequential GUIDs is not to promote the use of GUIDs as
50 | /// sortable entities. In fact, GUIDs generated very close together may
51 | /// have the same timestamp and are not guaranteed to be sequentially ordered
52 | /// at all. The intent is to increase performance when doing repeated
53 | /// inserts into database tables that have a clustered index on a GUID
54 | /// column, so that later entries do not have to be inserted into the middle
55 | /// of the table, but can simply be appended to the end.
56 | ///
57 | ///
58 | /// According to experiments, Microsoft SQL Server sorts GUID values using
59 | /// the least significant six bytes of the Data4 block; therefore, GUIDs being
60 | /// generated for use with SQL Server should pass a
61 | /// value of SequentialAtEnd. GUIDs generated for most other database
62 | /// types should be passed a value of
63 | /// SequentialAsString or SequentialAsByteArray.
64 | ///
65 | ///
66 | /// Various standards already define a time-based UUID; however, the
67 | /// format specified by these standards splits the timestamp into
68 | /// several components, limiting its usefulness as a sequential ID.
69 | /// Additionally, the format used for such UUIDs is not compatible
70 | /// with the GUID ordering on Microsoft SQL Server.
71 | ///
72 | ///
73 | public static Guid Create(SequentialGuidType guidType)
74 | {
75 | // We start with 16 bytes of cryptographically strong random data.
76 | byte[] randomBytes = new byte[10];
77 | SequentialGuid.RandomGenerator.GetBytes(randomBytes);
78 |
79 | // An alternate method: use a normally-created GUID to get our initial
80 | // random data:
81 | // byte[] randomBytes = Guid.NewGuid().ToByteArray();
82 | // This is faster than using RNGCryptoServiceProvider, but I don't
83 | // recommend it because the .NET Framework makes no guarantee of the
84 | // randomness of GUID data, and future versions (or different
85 | // implementations like Mono) might use a different method.
86 |
87 | // Now we have the random basis for our GUID. Next, we need to
88 | // create the six-byte block which will be our timestamp.
89 |
90 | // We start with the number of milliseconds that have elapsed since
91 | // DateTime.MinValue. This will form the timestamp. There's no use
92 | // being more specific than milliseconds, since DateTime.Now has
93 | // limited resolution.
94 |
95 | // Using millisecond resolution for our 48-bit timestamp gives us
96 | // about 5900 years before the timestamp overflows and cycles.
97 | // Hopefully this should be sufficient for most purposes. :)
98 | long timestamp = DateTime.UtcNow.Ticks / 10000L;
99 |
100 | // Then get the bytes
101 | byte[] timestampBytes = BitConverter.GetBytes(timestamp);
102 |
103 | // Since we're converting from an Int64, we have to reverse on
104 | // little-endian systems.
105 | if (BitConverter.IsLittleEndian)
106 | {
107 | Array.Reverse(timestampBytes);
108 | }
109 |
110 | byte[] guidBytes = new byte[16];
111 |
112 | switch (guidType)
113 | {
114 | case SequentialGuidType.SequentialAsString:
115 | case SequentialGuidType.SequentialAsBinary:
116 |
117 | // For string and byte-array version, we copy the timestamp first, followed
118 | // by the random data.
119 | Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6);
120 | Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10);
121 |
122 | // If formatting as a string, we have to compensate for the fact
123 | // that .NET regards the Data1 and Data2 block as an Int32 and an Int16,
124 | // respectively. That means that it switches the order on little-endian
125 | // systems. So again, we have to reverse.
126 | if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian)
127 | {
128 | Array.Reverse(guidBytes, 0, 4);
129 | Array.Reverse(guidBytes, 4, 2);
130 | }
131 |
132 | break;
133 |
134 | case SequentialGuidType.SequentialAtEnd:
135 |
136 | // For sequential-at-the-end versions, we copy the random data first,
137 | // followed by the timestamp.
138 | Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10);
139 | Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6);
140 | break;
141 | }
142 |
143 | return new Guid(guidBytes);
144 | }
145 | }
146 | }
--------------------------------------------------------------------------------
/SequentialGuid/Enums/SequentialGuidType.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright © Jeremy H. Todd 2011
4 | //
5 | //-----------------------------------------------------------------------
6 | namespace SequentialGuid
7 | {
8 | using System;
9 |
10 | ///
11 | /// Describes the type of a sequential GUID value.
12 | ///
13 | public enum SequentialGuidType
14 | {
15 | ///
16 | /// The GUID should be sequential when formatted using the
17 | /// method.
18 | ///
19 | SequentialAsString,
20 |
21 | ///
22 | /// The GUID should be sequential when formatted using the
23 | /// method.
24 | ///
25 | SequentialAsBinary,
26 |
27 | ///
28 | /// The sequential portion of the GUID should be located at the end
29 | /// of the Data4 block.
30 | ///
31 | SequentialAtEnd
32 | }
33 | }
--------------------------------------------------------------------------------
/SequentialGuid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright © Jeremy H. Todd 2011
4 | //
5 | //-----------------------------------------------------------------------
6 |
7 | using System.Reflection;
8 | using System.Runtime.CompilerServices;
9 | using System.Runtime.InteropServices;
10 |
11 | // General Information about an assembly is controlled through the following
12 | // set of attributes. Change these attribute values to modify the information
13 | // associated with an assembly.
14 | [assembly: AssemblyTitle("SequentialGuid")]
15 | [assembly: AssemblyDescription("An example library demonstrating the creation of sequential GUID values suitable for use as high-performance primary keys in various database systems.")]
16 | [assembly: AssemblyConfiguration("")]
17 | [assembly: AssemblyCompany("Jeremy H. Todd")]
18 | [assembly: AssemblyProduct("SequentialGuid")]
19 | [assembly: AssemblyCopyright("Copyright © Jeremy H. Todd 2012")]
20 | [assembly: AssemblyTrademark("")]
21 | [assembly: AssemblyCulture("")]
22 |
23 | // Setting ComVisible to false makes the types in this assembly not visible
24 | // to COM components. If you need to access a type in this assembly from
25 | // COM, set the ComVisible attribute to true on that type.
26 | [assembly: ComVisible(false)]
27 |
28 | // The following GUID is for the ID of the typelib if this project is exposed to COM
29 | [assembly: Guid("d202a529-423c-4ccf-96c9-b4e0d30c17d2")]
30 |
31 | // Version information for an assembly consists of the following four values:
32 | //
33 | // Major Version
34 | // Minor Version
35 | // Build Number
36 | // Revision
37 | //
38 | // You can specify all the values or you can default the Build and Revision Numbers
39 | // by using the '*' as shown below:
40 | // [assembly: AssemblyVersion("1.0.*")]
41 | [assembly: AssemblyVersion("1.0.0.0")]
42 | [assembly: AssemblyFileVersion("1.0.0.0")]
43 |
--------------------------------------------------------------------------------
/SequentialGuid/SequentialGuid.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {52EE6D7A-286D-44D1-B189-F1F027808E61}
8 | Library
9 | Properties
10 | SequentialGuid
11 | SequentialGuid
12 | v4.0
13 | 512
14 |
15 | 1
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | True
26 | False
27 | False
28 | False
29 | False
30 | True
31 | True
32 | True
33 | True
34 | True
35 | True
36 | True
37 | True
38 | True
39 | True
40 | True
41 | True
42 | True
43 | True
44 | True
45 | False
46 | False
47 |
48 |
49 |
50 |
51 |
52 |
53 | True
54 | Full
55 | Build
56 | 2
57 |
58 |
59 | pdbonly
60 | true
61 | bin\Release\
62 | TRACE
63 | prompt
64 | 4
65 | True
66 | True
67 | True
68 | False
69 | False
70 | False
71 | False
72 | False
73 | False
74 | False
75 | False
76 | False
77 | False
78 | False
79 | False
80 | True
81 | False
82 | False
83 | True
84 | True
85 | False
86 | True
87 |
88 |
89 |
90 |
91 |
92 |
93 | True
94 | Preconditions
95 | Build
96 | 0
97 | true
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
115 |
--------------------------------------------------------------------------------