Comment puis-je faire ceci :
private decimal _SnachCount;
[Required]
[DataType("decimal(16 ,3")]
public decimal SnachCount
{
get { return _SnachCount; }
set { _SnachCount = value; }
}
private decimal _MinimumStock;
[Required]
[DataType("decimal(16 ,3")]
public decimal MinimumStock
{
get { return _MinimumStock; }
set { _MinimumStock = value; }
}
private decimal _MaximumStock;
[Required]
[DataType("decimal(16 ,3")]
public decimal MaximumStock
{
get { return _MaximumStock; }
set { _MaximumStock = value; }
}
Après avoir généré la base de données par cette partie de mon modèle, ces trois colonnes de type sont décimales (18,2), pourquoi? quelle est cette erreur de code? Comment puis je faire ça ?
L'attribut DataType
est un attribut de validation. Vous devez le faire en utilisant ModelBuilder.
public class MyContext : DbContext
{
public DbSet<MyClass> MyClass;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyClass>().Property(x => x.SnachCount).HasPrecision(16, 3);
modelBuilder.Entity<MyClass>().Property(x => x.MinimumStock).HasPrecision(16, 3);
modelBuilder.Entity<MyClass>().Property(x => x.MaximumStock).HasPrecision(16, 3);
}
}
Vous pouvez modifier toutes les propriétés décimales de la base de données. Dans votre DBContext dans la méthode OnModelCreating, ajoutez une ligne:
modelBuilder.Properties<decimal>().Configure(c => c.HasPrecision(18, 3));
Ceci est copié de la réponse que j'ai postée à la même question ici; https://stackoverflow.com/a/15386883/1186032 .
J'ai passé un bon moment à créer un attribut personnalisé pour cela:
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public sealed class DecimalPrecisionAttribute : Attribute
{
public DecimalPrecisionAttribute(byte precision, byte scale)
{
Precision = precision;
Scale = scale;
}
public byte Precision { get; set; }
public byte Scale { get; set; }
}
l'utiliser comme ça
[DecimalPrecision(20,10)]
public Nullable<decimal> DeliveryPrice { get; set; }
et la magie se produit lors de la création du modèle avec une certaine réflexion
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
foreach (Type classType in from t in Assembly.GetAssembly(typeof(DecimalPrecisionAttribute)).GetTypes()
where t.IsClass && t.Namespace == "YOURMODELNAMESPACE"
select t)
{
foreach (var propAttr in classType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetCustomAttribute<DecimalPrecisionAttribute>() != null).Select(
p => new { prop = p, attr = p.GetCustomAttribute<DecimalPrecisionAttribute>(true) }))
{
var entityConfig = modelBuilder.GetType().GetMethod("Entity").MakeGenericMethod(classType).Invoke(modelBuilder, null);
ParameterExpression param = ParameterExpression.Parameter(classType, "c");
Expression property = Expression.Property(param, propAttr.prop.Name);
LambdaExpression lambdaExpression = Expression.Lambda(property, true,
new ParameterExpression[]
{param});
DecimalPropertyConfiguration decimalConfig;
if (propAttr.prop.PropertyType.IsGenericType && propAttr.prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
MethodInfo methodInfo = entityConfig.GetType().GetMethods().Where(p => p.Name == "Property").ToList()[7];
decimalConfig = methodInfo.Invoke(entityConfig, new[] { lambdaExpression }) as DecimalPropertyConfiguration;
}
else
{
MethodInfo methodInfo = entityConfig.GetType().GetMethods().Where(p => p.Name == "Property").ToList()[6];
decimalConfig = methodInfo.Invoke(entityConfig, new[] { lambdaExpression }) as DecimalPropertyConfiguration;
}
decimalConfig.HasPrecision(propAttr.attr.Precision, propAttr.attr.Scale);
}
}
}
la première partie consiste à obtenir toutes les classes dans le modèle (mon attribut personnalisé est défini dans cet assembly, donc je l'ai utilisé pour obtenir l'assembly avec le modèle)
le deuxième foreach obtient toutes les propriétés de cette classe avec l'attribut personnalisé et l'attribut lui-même afin que je puisse obtenir les données de précision et d'échelle
après ça je dois appeler
modelBuilder.Entity<MODEL_CLASS>().Property(c=> c.PROPERTY_NAME).HasPrecision(PRECITION,SCALE);
donc j'appelle le modelBuilder.Entity () par réflexion et le stocke dans la variable entityConfig puis je construis l'expression lambda "c => c.PROPERTY_NAME"
Après cela, si la décimale est nulle, j'appelle le
Property(Expression<Func<TStructuralType, decimal?>> propertyExpression)
méthode (j'appelle cela par la position dans le tableau, ce n'est pas l'idéal je sais, toute aide sera très appréciée)
et si ce n'est pas nullable j'appelle le
Property(Expression<Func<TStructuralType, decimal>> propertyExpression)
méthode.
Ayant la DecimalPropertyConfiguration j'appelle la méthode HasPrecision.
Donc, ce que j'ai travaillé pour moi est le suivant:
public class RestaurantItemEntity : BaseEntity
{
[Column(TypeName = "VARCHAR(128)")]
[StringLength(128)]
[Required]
public string Name { get; set; }
[Column(TypeName = "VARCHAR(1024)")]
[StringLength(1024)]
public string Description { get; set; }
[Column(TypeName = "decimal(16,2)")]
[Required]
public decimal Price { get; set; }
[Required]
public RestaurantEntity Restaurant { get; set; }
}
Il s'agit du code EF en premier pour le noyau .NET.
Vous pouvez également définir la précision des décimales en utilisant l'approche de mappage de modèle en premier code comme ceci:
public class MyEntityMapping : EntityTypeConfiguration<MyEntity>
{
public MyEntityMapping()
{
HasKey(x => x.Id);
Property(x => x.Id).IsRequired();
// .HasPrecision(precision, scale)
// 'precision' = total number of digits stored,
// regardless of where the decimal point falls
// 'scale' = number of decimal places stored
Property(x => x.DecimalItem).IsRequired().HasPrecision(16, 6);
}
}