Ich experimentiere mit diesem Code-First-Ansatz, finde aber jetzt heraus, dass eine Eigenschaft vom Typ System.Decimal einer SQL-Spalte vom Typ Dezimal (18, 0) zugeordnet wird.
Wie stelle ich die Genauigkeit der Datenbankspalte ein?
c#
.net
entity-framework
ef-code-first
decimal
Dave Van den Eynde
quelle
quelle
[Column(TypeName = "decimal(18,4)")]
Attribut für Ihre Dezimaleigenschaften zu verwendenAntworten:
Die Antwort von Dave Van den Eynde ist jetzt veraltet. Es gibt zwei wichtige Änderungen: Ab EF 4.1 lautet die ModelBuilder-Klasse jetzt DbModelBuilder und es gibt jetzt eine DecimalPropertyConfiguration.HasPrecision-Methode mit der Signatur:
Dabei ist Genauigkeit die Gesamtzahl der Stellen, die die Datenbank speichert, unabhängig davon, wo der Dezimalpunkt liegt, und Skalierung die Anzahl der Dezimalstellen, die gespeichert werden.
Daher ist es nicht erforderlich, die gezeigten Eigenschaften zu durchlaufen, sondern die können nur von aufgerufen werden
quelle
System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder
base.OnModelCreating(modelBuilder);
. War das beabsichtigt oder nur ein Opfer der Online-Eingabe von Code anstelle einer IDE?Wenn Sie die Genauigkeit für alle
decimals
in EF6 festlegen möchten, können Sie die Standardkonvention ersetzen, dieDecimalPropertyConvention
inDbModelBuilder
:Die Standardeinstellung
DecimalPropertyConvention
in EF6 ordnetdecimal
Eigenschaften zudecimal(18,2)
Spalten zu.Wenn Sie nur möchten, dass einzelne Eigenschaften eine bestimmte Genauigkeit haben, können Sie die Genauigkeit für die Eigenschaft der Entität wie folgt festlegen
DbModelBuilder
:Oder fügen Sie eine
EntityTypeConfiguration<>
für die Entität hinzu, die die Genauigkeit angibt:quelle
Ich hatte eine schöne Zeit, ein benutzerdefiniertes Attribut dafür zu erstellen:
benutze es so
und die Magie geschieht bei der Modellerstellung mit einigen Überlegungen
Der erste Teil besteht darin, alle Klassen im Modell abzurufen (mein benutzerdefiniertes Attribut ist in dieser Assembly definiert, daher habe ich das verwendet, um die Assembly mit dem Modell abzurufen).
Das zweite foreach erhält alle Eigenschaften in dieser Klasse mit dem benutzerdefinierten Attribut und dem Attribut selbst, damit ich die Genauigkeits- und Skalierungsdaten erhalten kann
danach muss ich anrufen
Also rufe ich den modelBuilder.Entity () durch Reflektion auf und speichere ihn in der entityConfig-Variablen. Dann baue ich den Lambda-Ausdruck "c => c.PROPERTY_NAME"
Danach, wenn die Dezimalzahl nullbar ist, rufe ich die
Methode (ich nenne dies durch die Position im Array, es ist nicht ideal, ich weiß, jede Hilfe wird sehr geschätzt)
und wenn es nicht nullbar ist, rufe ich das an
Methode.
Mit der DecimalPropertyConfiguration rufe ich die HasPrecision-Methode auf.
quelle
MethodInfo methodInfo = entityConfig.GetType().GetMethod("Property", new[] { lambdaExpression.GetType() });
, um die richtige Überlastung zu bekommen. scheint soweit zu funktionieren.Mit dem
DecimalPrecisonAttribute
von KinSlayerUY können Sie in EF6 eine Konvention erstellen, die einzelne Eigenschaften behandelt, die das Attribut haben (im Gegensatz zum Festlegen desDecimalPropertyConvention
Gleichen in dieser Antwort, das sich auf alle Dezimaleigenschaften auswirkt).Dann in Ihrem
DbContext
:quelle
Precision
, empfehle ich, die Obergrenze auf 28 zu setzen (also> 28
in Ihrem Zustand). Laut MSDN-DokumentationSystem.Decimal
können maximal 28 bis 29 Stellen Genauigkeit dargestellt werden ( msdn.microsoft.com/en-us/library/364x0z75.aspx ). Außerdem wird das AttributScale
als deklariertbyte
, was bedeutet, dass Ihre Vorbedingungattribute.Scale < 0
nicht erforderlich ist.System.Decimal
jedoch nicht. Daher macht es keinen Sinn, die Obergrenze auf etwas größer als 28 zu setzen;System.Decimal
kann anscheinend keine so großen Zahlen darstellen. Beachten Sie auch, dass dieses Attribut für andere Datenanbieter als SQL Server nützlich ist. Beispielsweisenumeric
unterstützt der Typ von PostgreSQL eine Genauigkeit von bis zu 131072 Stellen.decimal(38,9)
Spalte haben, halten Sie diese gerne,System.Decimal.MaxValue
einedecimal(28,9)
Spalte jedoch nicht. Es gibt keinen Grund, die Genauigkeit auf nur 28 zu beschränken.Anscheinend können Sie die DbContext.OnModelCreating () -Methode überschreiben und die Genauigkeit wie folgt konfigurieren:
Aber dies ist ein ziemlich langwieriger Code, wenn Sie ihn mit all Ihren preisbezogenen Eigenschaften ausführen müssen. Deshalb habe ich mir Folgendes ausgedacht:
Es wird empfohlen, die Basismethode aufzurufen, wenn Sie eine Methode überschreiben, obwohl die Basisimplementierung nichts bewirkt.
Update: Dieser Artikel war auch sehr hilfreich.
quelle
base.OnModelCreating(modelBuilder);
notwendig ist. Aus den DbContext-Metadaten in 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 Version 6 (Alpha, rc1) enthält sogenannte benutzerdefinierte Konventionen . So stellen Sie die Dezimalgenauigkeit ein:
Referenz:
quelle
Dies funktioniert bei ersten Migrationen mit EF Core-Code wie hier beschrieben .
quelle
The store type 'decimal(18,2)' could not be found in the SqlServer provider manifest
Diese Codezeile könnte eine einfachere Möglichkeit sein, dasselbe zu erreichen:
quelle
- FÜR EF KERN - mit System.ComponentModel.DataAnnotations;
Verwendung
[Column
(TypeName
= "decimal
( Präzision , Skalierung )")]
Präzision = Gesamtzahl der verwendeten Zeichen
Skala = Gesamtzahl nach dem Punkt. (leicht zu verwirren)
Beispiel :
Weitere Details finden Sie hier: https://docs.microsoft.com/en-us/ef/core/modeling/relational/data-types
quelle
In EF6
quelle
Sie können EF jederzeit anweisen, dies mit Konventionen in der Context-Klasse in der OnModelCreating-Funktion wie folgt zu tun:
Dies gilt nur für Code First EF fyi und für alle Dezimaltypen, die der Datenbank zugeordnet sind.
quelle
Remove<DecimalPropertyConvention>();
vor dem kommtAdd(new DecimalPropertyConvention(18, 4));
. Ich finde es seltsam, dass nicht nur automatisch überschrieben wird.Verwenden von
Sie können dieses Attribut einfach in Ihr Modell einfügen:
quelle
Weitere Informationen finden Sie unter MSDN - Facette des Entitätsdatenmodells. http://msdn.microsoft.com/en-us/library/ee382834.aspx Vollständig empfohlen.
quelle
Tatsächlich für EntityFrameworkCore 3.1.3:
eine Lösung in OnModelCreating:
quelle
Das benutzerdefinierte Attribut von KinSlayerUY hat bei mir gut funktioniert, aber ich hatte Probleme mit ComplexTypes. Sie wurden als Entitäten im Attributcode zugeordnet und konnten dann nicht als ComplexType zugeordnet werden.
Ich habe daher den Code erweitert, um dies zu ermöglichen:
quelle
@ Mark007, ich habe die Typauswahlkriterien geändert, um die DbSet <> -Eigenschaften des DbContext zu nutzen. Ich denke, das ist sicherer, weil es Zeiten gibt, in denen Sie Klassen im angegebenen Namespace haben, die nicht Teil der Modelldefinition sein sollten oder aber keine Entitäten sind. Oder Ihre Entitäten befinden sich in separaten Namespaces oder separaten Assemblys und werden zu einem einzigen Kontext zusammengefasst.
Auch wenn dies unwahrscheinlich ist, halte ich es nicht für sicher, sich auf die Reihenfolge der Methodendefinitionen zu verlassen. Daher ist es besser, sie anhand der Parameterliste herauszuholen. (.GetTypeMethods () ist eine Erweiterungsmethode, die ich für die Arbeit mit dem neuen TypeInfo-Paradigma erstellt habe und die Klassenhierarchien bei der Suche nach Methoden reduzieren kann.)
Beachten Sie, dass OnModelCreating diese Methode delegiert:
quelle