有没有办法使用 CodeFirst 设计为新的 Entity Framework 4.1 中的对象实现 Guid COMB 身份策略?我想设置 StoreGeneratedPattern 可以,但它仍然给我正常的 GUID。

有帮助吗?

解决方案

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

如果您希望数据库生成顺序Guids,则必须修改生成的表,这非常复杂,因为您必须找到自动生成的默认约束,删除它并创建新约束。这一切都可以在自定义数据库初始值设定项中完成。这里有我的示例代码:

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() 在我的例子中,它是由 FluentMigrator 迁移管理的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top