GUID COMB Strategy in EF

Is there a way to implement the Guid COMB identity strategy for objects in the new Entity Framework 4.1 using the CodeFirst design? I thought setting StoreGeneratedPattern would work, but it still gives me the usual GUIDs.

+8
c # guid entity-framework ef-migrations newsequentialid
May 23 '11 at 14:57
source share
3 answers

I assume that you are using SQL Server as your database. This is a good example of inconsistency between different MS tools. The SQL server command does not recommend using newid() as the default value for UNIQUEIDENTIFIER columns, and the ADO.NET command uses it if you specify the Guid property as auto-generated in the database. Instead, they should use newsequentialid() !

If you want the sequential Guides generated by the database, you have to modify the generated table, and this is really difficult, because you have to find the default auto-generated constraint, delete it and create a new constraint. All of this can be done in a custom database initializer. Here you have a sample code:

 class Program { static void Main(string[] args) { Database.SetInitializer(new CustomInitializer()); using (var context = new Context()) { context.TestEntities.Add(new TestEntity() { Name = "A" }); context.TestEntities.Add(new TestEntity() { Name = "B" }); context.SaveChanges(); } } } public class CustomInitializer : DropCreateDatabaseAlways<Context> { protected override void Seed(Context context) { base.Seed(context); context.Database.ExecuteSqlCommand(@" DECLARE @Name VARCHAR(100) SELECT @Name = O.Name FROM sys.objects AS O INNER JOIN sys.tables AS T ON O.parent_object_id = T.object_id WHERE O.type_desc LIKE 'DEFAULT_CONSTRAINT' AND O.Name LIKE 'DF__TestEntities__Id__%' AND T.Name = 'TestEntities' DECLARE @Sql NVARCHAR(2000) = 'ALTER TABLE TestEntities DROP Constraint ' + @Name EXEC sp_executesql @Sql ALTER TABLE TestEntities ADD CONSTRAINT IdDef DEFAULT NEWSEQUENTIALID() FOR Id"); } } public class TestEntity { public Guid Id { get; set; } public string Name { get; set; } } public class Context : DbContext { public DbSet<TestEntity> TestEntities { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<TestEntity>() .Property(e => e.Id) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); } } 
+8
May 23 '11 at 17:20
source share

Why worry about the default values ​​for Guid columns in a database? Why not just generate a Guid on the client, like any other value. This requires that you have a method in your client code that will generate COMB messages:

 public static Guid NewGuid() { var guidBinary = new byte[16]; Array.Copy( Guid.NewGuid().ToByteArray(), 0, guidBinary, 0, 8 ); Array.Copy( BitConverter.GetBytes( DateTime.Now.Ticks ), 0, guidBinary, 8, 8 ); return new Guid( guidBinary ); } 

One of the advantages of the Guide is that you can create them on the client without a trip back to the database.

+14
May 23 '11 at 17:36
source share

Easiest answer

 public class User { public User(Guid? id = null, DateTime? created = null) { if (id != null) Id = id; if (created != null) Created = created; } public User() { } [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime? Created { get; internal set; } [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid? Id { get; internal set; } } 

It is assumed that your database table is installed by default newsequentialid() , which in my case is controlled by FluentMigrator migrations.

+2
Aug 17 '11 at 20:10
source share



All Articles