GUID COMB стратегия в EF - PullRequest
       48

GUID COMB стратегия в EF

9 голосов
/ 23 мая 2011

Есть ли способ реализовать стратегию идентификации Guid COMB для объектов в новой Entity Framework 4.1, используя дизайн CodeFirst? Я думал, что установка StoreGeneratedPattern будет работать, но она все еще дает мне нормальные GUID.

Ответы [ 3 ]

16 голосов
/ 23 мая 2011

Зачем вообще беспокоиться о значениях по умолчанию для столбцов Guid в базе данных? Почему бы просто не генерировать Guid на клиенте, как любое другое значение. Для этого в вашем клиентском коде должен быть метод, который будет генерировать COMB-подобные направляющие:

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 является то, что вы можете сгенерировать их на клиенте без обратной передачи в базу данных.

9 голосов
/ 23 мая 2011

Полагаю, вы используете SQL-сервер в качестве базы данных. Это хороший пример несоответствия между различными инструментами MS. Команда SQL-сервера не рекомендует использовать newid() в качестве значения по умолчанию для столбцов UNIQUEIDENTIFIER, а команда ADO.NET использует его, если вы указали свойство Guid как автоматически сгенерированное в базе данных. Они должны использовать newsequentialid() вместо!

Если вам нужны последовательные направляющие, генерируемые базой данных, вы должны изменить сгенерированную таблицу, и она действительно сложна, потому что вы должны найти автоматически сгенерированное ограничение по умолчанию, отбросить его и создать новое ограничение. Все это можно сделать в пользовательском инициализаторе базы данных. Вот мой пример кода:

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);
    }
}
2 голосов
/ 18 августа 2011

Самый простой ответ

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.

...