entity-framework - use - npm entity framework core



Repetir/refletir através de todas as propriedades em todos os modelos EF para definir o Tipo de coluna (1)

No EF Core v1.1.0, você pode usar algo como isto:

foreach (var pb in modelBuilder.Model
    .GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?))
    .Select(p => modelBuilder.Entity(p.DeclaringEntityType.ClrType).Property(p.Name)))
{
    pb.ForSqlServerHasColumnType("decimal(13,4)");
}

Atualização: A partir do EF Core 2.0, o modelo é criado separadamente para cada provedor de banco de dados, portanto, os métodos HasAbcXyz são substituídos pelo HasXyz comum. O código atualizado (que também ignora as propriedades explicitamente configuradas) tem a seguinte aparência:

foreach (var property in modelBuilder.Model.GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
{
    if (property.Relational().ColumnType == null)
        property.Relational().ColumnType = "decimal(13,4)";
}

Meu cliente tem um padrão de armazenamento de decimais do SQL Server com uma especificação decimal (13,4). Como resultado, em um esquema muito grande e ainda em crescimento, tenho quase cem declarações como estas:

builder.Entity<MyObject>()
    .Property(x => x.MyField1)
    .ForSqlServerHasColumnType("decimal(13,4)");
builder.Entity<MyObject>()
    .Property(x => x.MyField2)
    .ForSqlServerHasColumnType("decimal(13,4)");
builder.Entity<MyObject2>()
    .Property(x => x.MyField1)
    .ForSqlServerHasColumnType("decimal(13,4)");

Se houver um recurso em que eu possa informar diretamente à EF que todos os decimais devem ser decimais (13,4) por padrão, eu gostaria de usá-lo. Caso contrário, posso usar a reflexão para percorrer todos os objetos / propriedades do modelo para fazer isso em algumas instruções?

Algo como:

foreach(var efObj in EntityFrameWorkObjects)
{
    foreach (var objProperty in efObj)
    {
        if (objProperty is decimal || objProperty is decimal?)
        {
            builder.Entity<efObj>()
                .Property(x => x.efObj)
                .ForSqlServerHasColumnType("decimal(13,4)");
        }
    }
}

A reflexão parece ser um ótimo caminho a percorrer, porque então eu posso implementar algumas de nossas outras convenções em que, se um objeto tiver um Nome e Descrição, o Nome será necessário e limitado a 256 caracteres.

Atualização: Eu segui o link no comentário de Ivan e o adaptei a isso, que funciona para mim:

foreach (var p in builder.Model
    .GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => 
        p.ClrType == typeof(decimal) ||
        p.ClrType == typeof(decimal?)))
{
    p.SqlServer().ColumnType = "decimal(13,4)";
}

Logo depois, ele forneceu uma resposta completa, que eu mudei levemente para trabalhar com decimal e com valor nulo:

foreach (var pb in builder.Model
    .GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => 
        p.ClrType == typeof(decimal) ||
        p.ClrType == typeof(decimal?))
    .Select(p => 
        builder.Entity(p.DeclaringEntityType.ClrType)
            .Property(p.Name)))
{
    pb.ForSqlServerHasColumnType("decimal(13,4)");
}

Ambas as abordagens funcionam!

Atualização 2: Eu tinha que ter meus objetos declarados como DbSet <> no contexto para o trabalho acima funcionar. Isso não parecia ser necessário quando eu estava definindo propriedades linha por linha.