Définissez la décimale (16, 3) pour une colonne dans le code First Approche dans EF4.3
-
14-11-2019 - |
Question
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 types de colonnes sont décimaux (18,2), pourquoi? Quelle est cette erreur de code? Comment puis je faire ça ?
La solution
La DataType
L'attribut est un attribut de validation. Vous devez le faire en utilisant le 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);
}
}
Autres conseils
Vous pouvez modifier toutes les propreties décimales dans la base de données. Dans votre DBContext dans la méthode OnModelCreating Ajouter une ligne:
modelBuilder.Properties<decimal>().Configure(c => c.HasPrecision(18, 3));
Ceci est copié à partir de la réponse que j'ai postée sur la même question ici; https://stackoverflow.com/a/15386883/1186032.
J'ai passé un bon moment à créer un attribut personnalisé pour ceci:
[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 à 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 du modèle (mon attribut personnalisé est défini dans cet assemblage, donc j'ai utilisé cela pour obtenir l'assemblage 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);
J'appelle donc le modelbuilder.entity () par réflexion et le stocker dans la variable EntityConfig puis je construis la "C => C.Property_name" Lambda Expression
Après cela, si la décimale est nullable, j'appelle le
Property(Expression<Func<TStructuralType, decimal?>> propertyExpression)
Méthode (j'appelle cela par la position dans le tableau, ce n'est pas 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 configuration decimalpropertyConfiguration, j'appelle la méthode Hasprecision.
Donc, ce que j'ai travaillé pour moi, c'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 d'abord du code EF pour .NET Core.
Vous pouvez également définir la précision des décimales à l'aide de l'approche de mappage du modèle de code 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);
}
}