Estoy experimentando con este enfoque de código primero, pero ahora descubro que una propiedad de tipo System.Decimal se asigna a una columna sql de tipo decimal (18, 0).
¿Cómo configuro la precisión de la columna de la base de datos?
c#
.net
entity-framework
ef-code-first
decimal
Dave Van den Eynde
fuente
fuente
[Column(TypeName = "decimal(18,4)")]
atributo para sus propiedades decimalesRespuestas:
La respuesta de Dave Van den Eynde está desactualizada. Hay 2 cambios importantes, desde EF 4.1 en adelante, la clase ModelBuilder ahora es DbModelBuilder y ahora hay un DecimalPropertyConfiguration.HasPrecision Method que tiene una firma de:
donde precisión es el número total de dígitos que almacenará la base de datos, independientemente de dónde caiga el punto decimal y la escala sea el número de lugares decimales que almacenará.
Por lo tanto, no es necesario recorrer las propiedades como se muestra, pero solo se puede llamar desde
fuente
System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder
base.OnModelCreating(modelBuilder);
. ¿Fue intencional o simplemente una víctima de escribir código en línea en lugar de en un IDE?Si desea establecer la precisión para todos
decimals
en EF6, puede reemplazar laDecimalPropertyConvention
convención predeterminada utilizada enDbModelBuilder
:El valor predeterminado
DecimalPropertyConvention
en EF6 asignadecimal
propiedades adecimal(18,2)
columnas.Si solo desea que las propiedades individuales tengan una precisión especificada, puede establecer la precisión de la propiedad de la entidad en
DbModelBuilder
:O agregue un
EntityTypeConfiguration<>
para la entidad que especifica la precisión:fuente
Me divertí mucho creando un atributo personalizado para esto:
usándolo así
y la magia ocurre en la creación del modelo con cierta reflexión
la primera parte es obtener todas las clases en el modelo (mi atributo personalizado se define en ese ensamblaje, así que lo usé para obtener el ensamblaje con el modelo)
el segundo foreach obtiene todas las propiedades de esa clase con el atributo personalizado, y el atributo en sí mismo para que pueda obtener los datos de precisión y escala
después de eso tengo que llamar
entonces llamo al modelBuilder.Entity () por reflexión y lo almaceno en la variable entityConfig luego construyo la expresión lambda "c => c.PROPERTY_NAME"
Después de eso, si el decimal es anulable, llamo al
método (lo llamo por la posición en la matriz, no es ideal, lo sé, cualquier ayuda será muy apreciada)
y si no es nulable llamo al
método.
Teniendo DecimalPropertyConfiguration llamo al método HasPrecision.
fuente
MethodInfo methodInfo = entityConfig.GetType().GetMethod("Property", new[] { lambdaExpression.GetType() });
para obtener la sobrecarga correcta. Parece funcionar hasta ahora.Usando el
DecimalPrecisonAttribute
KinSlayerUY, en EF6 puede crear una convención que manejará las propiedades individuales que tienen el atributo (en lugar de establecer el meDecimalPropertyConvention
gusta en esta respuesta que afectará todas las propiedades decimales).Luego en tu
DbContext
:fuente
Precision
, le recomiendo establecer el límite superior en 28 (> 28
en su condición). Según la documentación de MSDN,System.Decimal
solo puede representar un máximo de 28-29 dígitos de precisión ( msdn.microsoft.com/en-us/library/364x0z75.aspx ). Además, el atributo declaraScale
comobyte
, lo que significa que su condición previaattribute.Scale < 0
es innecesaria.System.Decimal
no. Por lo tanto, no tiene sentido establecer la condición previa del límite superior en algo mayor que 28;System.Decimal
no puede representar números tan grandes, aparentemente. Además, tenga en cuenta que este atributo es útil para proveedores de datos que no sean SQL Server. Por ejemplo, elnumeric
tipo de PostgreSQL admite hasta 131072 dígitos de precisión.decimal(38,9)
columna se mantendrá felizSystem.Decimal.MaxValue
pero ladecimal(28,9)
columna no. No hay razón para limitar la precisión a solo 28.Aparentemente, puede anular el método DbContext.OnModelCreating () y configurar la precisión de esta manera:
Pero este es un código bastante tedioso cuando tienes que hacerlo con todas tus propiedades relacionadas con el precio, así que se me ocurrió esto:
Es una buena práctica que llame al método base cuando anula un método, aunque la implementación base no haga nada.
Actualización: este artículo también fue muy útil.
fuente
base.OnModelCreating(modelBuilder);
sea necesario llamar . De los metadatos de DbContext en 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.
Entity Framework Ver 6 (Alpha, rc1) tiene algo llamado Convenciones personalizadas . Para establecer la precisión decimal:
Referencia:
fuente
esto funcionará con las primeras migraciones del código EF Core como se describe aquí .
fuente
The store type 'decimal(18,2)' could not be found in the SqlServer provider manifest
Esta línea de código podría ser una forma más sencilla de lograr lo mismo:
fuente
- PARA EF CORE - con el uso de System.ComponentModel.DataAnnotations;
uso
[Column
(TypeName
= "decimal
( precisión , escala )")]
Precisión = Número total de caracteres utilizados
Escala = Número total después del punto. (fácil de confundir)
Ejemplo :
Más detalles aquí: https://docs.microsoft.com/en-us/ef/core/modeling/relational/data-types
fuente
En EF6
fuente
Siempre puede decirle a EF que haga esto con convenciones en la clase Context en la función OnModelCreating de la siguiente manera:
Esto solo se aplica a Code First EF fyi y se aplica a todos los tipos decimales asignados a la base de datos.
fuente
Remove<DecimalPropertyConvention>();
llega antes delAdd(new DecimalPropertyConvention(18, 4));
. Creo que es extraño que no se anule automáticamente.Utilizando
Simplemente puede poner ese atributo en su modelo:
fuente
Puede encontrar más información sobre MSDN - faceta del modelo de datos de entidad. http://msdn.microsoft.com/en-us/library/ee382834.aspx Completamente recomendado.
fuente
Actual para EntityFrameworkCore 3.1.3:
alguna solución en OnModelCreating:
fuente
El atributo personalizado de KinSlayerUY funcionó muy bien para mí, pero tuve problemas con ComplexTypes. Se estaban mapeando como entidades en el código de atributo, por lo que no se podían mapear como ComplexType.
Por lo tanto, extendí el código para permitir esto:
fuente
@ Mark007, he cambiado los criterios de selección de tipo para utilizar las propiedades DbSet <> del DbContext. Creo que esto es más seguro porque hay momentos en los que tienes clases en el espacio de nombres dado que no deberían ser parte de la definición del modelo o son pero no son entidades. O sus entidades podrían residir en espacios de nombres separados o conjuntos separados y agruparse en un contexto.
Además, aunque es poco probable, no creo que sea seguro confiar en el orden de las definiciones de métodos, por lo que es mejor sacarlas con la lista de parámetros. (.GetTypeMethods () es un método de extensión que construí para trabajar con el nuevo paradigma TypeInfo y puede aplanar las jerarquías de clases al buscar métodos).
Tenga en cuenta que OnModelCreating delega a este método:
fuente