Estou experimentando essa abordagem de primeiro código, mas agora descubro que uma propriedade do tipo System.Decimal é mapeada para uma coluna sql do tipo decimal (18, 0).
Como defino a precisão da coluna do banco de dados?
c#
.net
entity-framework
ef-code-first
decimal
Dave Van den Eynde
fonte
fonte
[Column(TypeName = "decimal(18,4)")]
atributo para suas propriedades decimaisRespostas:
A resposta de Dave Van den Eynde está desatualizada. Há duas alterações importantes: a partir do EF 4.1, a classe ModelBuilder agora é DbModelBuilder e agora existe um método DecimalPropertyConfiguration.HasPrecision que possui uma assinatura de:
onde precisão é o número total de dígitos que o banco de dados armazenará, independentemente de onde o ponto decimal cai e a escala é o número de casas decimais que ele armazenará.
Portanto, não há necessidade de iterar pelas propriedades, como mostrado, mas elas podem ser chamadas a partir de
fonte
System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder
base.OnModelCreating(modelBuilder);
. Isso foi intencional ou apenas uma vítima de digitar código on-line em vez de em um IDE?Se você deseja definir a precisão para todos
decimals
no EF6, substitua aDecimalPropertyConvention
convenção padrão usada emDbModelBuilder
:O padrão
DecimalPropertyConvention
no EF6 mapeiadecimal
propriedades paradecimal(18,2)
colunas.Se você deseja que apenas propriedades individuais tenham uma precisão especificada, defina a precisão da propriedade da entidade em
DbModelBuilder
:Ou adicione um
EntityTypeConfiguration<>
para a entidade que especifica a precisão:fonte
Eu me diverti bastante criando um Atributo personalizado para isso:
usando assim
e a mágica acontece na criação do modelo com alguma reflexão
a primeira parte é obter todas as classes no modelo (meu atributo personalizado é definido nessa montagem, então eu usei isso para obter a montagem com o modelo)
o segundo foreach obtém todas as propriedades dessa classe com o atributo customizado e o próprio atributo para que eu possa obter os dados de precisão e escala
depois disso eu tenho que ligar
então eu chamo o modelBuilder.Entity () por reflexão e armazeno-o na variável entityConfig, então construo a expressão lambda "c => c.PROPERTY_NAME"
Depois disso, se o decimal for anulável, chamo o
método (eu chamo isso de posição na matriz, não é o ideal, eu sei, qualquer ajuda será muito apreciada)
e se não for anulável eu chamo o
método.
Tendo o DecimalPropertyConfiguration, chamo o método HasPrecision.
fonte
MethodInfo methodInfo = entityConfig.GetType().GetMethod("Property", new[] { lambdaExpression.GetType() });
para obter a sobrecarga correta. parece funcionar até agora.Usando o
DecimalPrecisonAttribute
KinSlayerUY, no EF6, você pode criar uma convenção que manipulará propriedades individuais que possuem o atributo (em vez de definir oDecimalPropertyConvention
mesmo nesta resposta que afetará todas as propriedades decimais).Então no seu
DbContext
:fonte
Precision
, recomendo definir o limite superior para 28 (portanto,> 28
em sua condição). De acordo com a documentação do MSDN,System.Decimal
pode representar apenas um máximo de 28 a 29 dígitos de precisão ( msdn.microsoft.com/en-us/library/364x0z75.aspx ). Além disso, o atributo declaraScale
comobyte
, o que significa que sua préattribute.Scale < 0
- condição é desnecessária.System.Decimal
não. Portanto, não faz sentido definir a pré-condição do limite superior para algo maior que 28;System.Decimal
aparentemente não pode representar números tão grandes. Além disso, esteja ciente de que esse atributo é útil para outros provedores de dados que não o SQL Server. Por exemplo, onumeric
tipo do PostgreSQL suporta até 131072 dígitos de precisão.decimal(38,9)
coluna manterá feliz o botão,System.Decimal.MaxValue
mas umadecimal(28,9)
coluna não. Não há nenhuma razão para limitar a precisão com apenas 28.Aparentemente, você pode substituir o método DbContext.OnModelCreating () e configurar a precisão assim:
Mas esse é um código bastante tedioso quando você precisa fazer isso com todas as suas propriedades relacionadas a preços, então eu vim com isso:
É uma boa prática chamar o método base quando você substitui um método, mesmo que a implementação básica não faça nada.
Atualização: este artigo também foi muito útil.
fonte
base.OnModelCreating(modelBuilder);
é necessário. Dos metadados do DbContext no VS:The default implementation of this method does nothing, but it can be overridden in a derived class such that the model can be further configured before it is locked down.
O Entity Framework Ver 6 (Alpha, rc1) possui algo chamado Convenções personalizadas . Para definir a precisão decimal:
Referência:
fonte
isso funcionará com as primeiras migrações do código EF Core, conforme descrito aqui .
fonte
The store type 'decimal(18,2)' could not be found in the SqlServer provider manifest
essa linha de código pode ser uma maneira mais simples de realizar o mesmo:
fonte
- PARA EF CORE - com o uso de System.ComponentModel.DataAnnotations;
use
[Column
(TypeName
= "decimal
( precisão , escala )")]
Precisão = número total de caracteres usados
Escala = Número total após o ponto. (fácil de se confundir)
Exemplo :
Mais detalhes aqui: https://docs.microsoft.com/en-us/ef/core/modeling/relational/data-types
fonte
No EF6
fonte
Você sempre pode dizer ao EF para fazer isso com convenções na classe Context na função OnModelCreating da seguinte maneira:
Isso se aplica apenas ao Code First EF fyi e se aplica a todos os tipos decimais mapeados para o banco de dados.
fonte
Remove<DecimalPropertyConvention>();
venha antes doAdd(new DecimalPropertyConvention(18, 4));
. Eu acho estranho que não seja substituído automaticamente.Usando
Você pode simplesmente colocar esse atributo no seu modelo:
fonte
Você pode encontrar mais informações sobre o MSDN - faceta do modelo de dados da entidade. http://msdn.microsoft.com/en-us/library/ee382834.aspx Totalmente recomendado.
fonte
Real para EntityFrameworkCore 3.1.3:
alguma solução no OnModelCreating:
fonte
O atributo personalizado do KinSlayerUY funcionou muito bem para mim, mas tive problemas com o ComplexTypes. Eles estavam sendo mapeados como entidades no código do atributo e, portanto, não podiam ser mapeados como um ComplexType.
Portanto, estendi o código para permitir isso:
fonte
@ Mark007, alterei os critérios de seleção de tipo para rodar nas propriedades DbSet <> do DbContext. Eu acho que isso é mais seguro, porque há momentos em que você tem classes no namespace fornecido que não devem fazer parte da definição do modelo ou são, mas não são entidades. Ou suas entidades podem residir em namespaces ou assemblies separados e serem reunidos em um único contexto.
Além disso, apesar de improvável, não acho seguro confiar na ordenação de definições de métodos, por isso é melhor retirá-las pela lista de Parâmetros. (.GetTypeMethods () é um método de extensão que eu criei para trabalhar com o novo paradigma TypeInfo e pode nivelar hierarquias de classes ao procurar métodos).
Observe que OnModelCreating delega para esse método:
fonte