web-dev-qa-db-fra.com

Définissez la décimale (16, 3) pour une colonne dans Code First Approach dans EF4.3

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 ?

39
Ali Foroughi

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);
    }
}
74
dknaack

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));
31
Robert

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.

20
KinSlayerUY

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.

6
Vulovic Vukasin

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);
    }
}
1
RickL