Pregunta

Hay alguna forma de implementar el Guid PEINE estrategia de identidad de los objetos en la nueva Entity Framework 4.1 uso de la CodeFirst diseño?Pensé que la configuración de la StoreGeneratedPattern iba a funcionar, pero todavía me da normal Guid.

¿Fue útil?

Solución

Supongo que usted está utilizando SQL server como base de datos.Este es buen ejemplo de la inconsistencia entre las diferentes herramientas de MS.Equipo de SQL server no recomendamos el uso de newid() como valor por defecto para UNIQUEIDENTIFIER columnas y ADO.NET equipo de usarlo si usted especifique Guid propiedad como autogenerado en la base de datos.Se debe utilizar newsequentialid() en lugar de eso!

Si desea secuencial Guid generado por la base de datos debe modificar la tabla generada y es realmente complejo, ya que debe encontrar autogenerado restricción predeterminada, la caída de ella y crear nueva restricción.Todo esto puede ser hecho en base de datos personalizada de inicializador.Aquí tenéis mi código de ejemplo:

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

Otros consejos

¿Por qué preocuparse por defecto para Guid columnas en la base de datos?¿Por qué no acaba de generar el Guid en el cliente como cualquier otro valor.Que requiere que usted tenga un método en el código de cliente que va a generar PEINE-como 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 );
}

Una de las ventajas de la Guid es específicamente que puede generar en el cliente sin necesidad de un viaje de ida a la base de datos.

La respuesta más sencilla

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

Esto asume que usted tiene la base de datos conjunto de la tabla con el valor predeterminado de newsequentialid() que en mi caso es administrado por FluentMigrator las migraciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top