Wie kann ich das machen :
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; }
}
Nach dem Generieren der Datenbank mit diesem Teil meines Modells sind diese drei Spaltentypen dezimal (18,2). Warum? Was ist dieser Codefehler? wie kann ich das machen ?
Das DataType
Attribut ist ein Validierungsattribut. Sie müssen dies mit dem ModelBuilder tun.
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);
}
}
Sie können alle Dezimaleigenschaften in der Datenbank ändern. In Ihrem DBContext in der Methode OnModelCreating add line:
modelBuilder.Properties<decimal>().Configure(c => c.HasPrecision(18, 3));
Dies ist von der Antwort kopiert, die ich hier auf dieselbe Frage gepostet habe. https://stackoverflow.com/a/15386883/1186032 .
Ich hatte eine schöne Zeit, ein benutzerdefiniertes Attribut dafür zu erstellen:
[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; }
}
benutze es so
[DecimalPrecision(20,10)]
public Nullable<decimal> DeliveryPrice { get; set; }
und die Magie geschieht bei der Modellerstellung mit einigem Nachdenken
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);
}
}
}
der erste Teil besteht darin, alle Klassen im Modell abzurufen (mein benutzerdefiniertes Attribut ist in dieser Assembly definiert, daher habe ich dieses verwendet, um die Assembly mit dem Modell abzurufen.)
das zweite foreach ruft alle Eigenschaften in dieser Klasse mit dem benutzerdefinierten Attribut und dem Attribut selbst ab, damit ich die Genauigkeits- und Skalierungsdaten abrufen kann
danach muss ich anrufen
modelBuilder.Entity<MODEL_CLASS>().Property(c=> c.PROPERTY_NAME).HasPrecision(PRECITION,SCALE);
also rufe ich die modelBuilder.Entity () durch Reflektion auf und speichere sie in der entityConfig-Variablen. Dann erstelle ich den Lambda-Ausdruck "c => c.PROPERTY_NAME"
Danach, wenn die Dezimalstelle nullable ist, rufe ich das auf
Property(Expression<Func<TStructuralType, decimal?>> propertyExpression)
methode (ich nenne das die Position im Array, es ist nicht ideal, ich weiß, jede Hilfe wird sehr geschätzt)
und wenn es nicht nullable ist, nenne ich das
Property(Expression<Func<TStructuralType, decimal>> propertyExpression)
methode.
Mit der DecimalPropertyConfiguration rufe ich die HasPrecision-Methode auf.
Also, was ich für mich arbeiten bekam, ist das:
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; }
}
Dies ist der erste EF-Code für .NET Core.
Sie können die Genauigkeit von Dezimalstellen auch mit dem Code-First-Modellzuordnungsansatz wie folgt festlegen:
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);
}
}