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

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

4 ответа

Решение

Я полагаю, вы используете SQL-сервер в качестве базы данных. Это хороший пример несоответствия между различными инструментами MS. Команда SQL Server не рекомендует использовать 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);
    }
}

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

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

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.

если вы используете SQL Server, когда свойство GUID настроено как значение, создаваемое при добавлении, поставщик автоматически выполняет создание значения на стороне клиента, используя алгоритм для создания оптимальных последовательных значений GUID. см. для получения дополнительной информации.

https://learn.microsoft.com/en-us/ef/core/modeling/generated-properties?tabs=fluent-api

Другие вопросы по тегам