EF中的GUID COMB策略

使用CodeFirstdevise,有没有办法在新的entity framework4.1中为对象实现Guid COMB标识策略? 我认为设置StoreGeneratedPattern会工作,但它仍然给我正常的GUID。

我猜你正在使用SQL服务器作为你的数据库。 这是不同MS工具之间不一致的好例子。 SQL Server团队不build议使用newid()作为UNIQUEIDENTIFIER列的默认值,如果您在数据库中将Guid属性指定为自动生成,ADO.NET团队将使用它。 他们应该使用newsequentialid()来代替!

如果你想要数据库生成的顺序Guid,你必须修改生成的表,这是非常复杂的,因为你必须find自动生成的默认约束,放下它,并创build新的约束。 这一切都可以在自定义数据库初始化器中完成。 在这里你有我的示例代码:

 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); } } 

为什么要担心数据库中Guid列的默认值? 为什么不像其他值那样在客户端生成Guid? 这就要求你在你的客户端代码中有一个方法来生成类COMB的GUID:

 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 ); } 

Guid的优点之一就是你可以在客户端生成它们,而不需要往返数据库。

最简单的答案

 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; } } 

这假设你有你的数据库表默认设置newsequentialid newsequentialid()在我的情况下是由FluentMigrator迁移pipe理。