Eksperymentuję z tym podejściem opartym na pierwszym kodzie, ale teraz dowiaduję się, że właściwość typu System.Decimal jest odwzorowywana na kolumnę SQL typu dziesiętnego (18, 0).
Jak ustawić dokładność kolumny bazy danych?
c#
.net
entity-framework
ef-code-first
decimal
Dave Van den Eynde
źródło
źródło
[Column(TypeName = "decimal(18,4)")]
atrybutu dla właściwości dziesiętnychOdpowiedzi:
Odpowiedź Dave'a Van den Eynde jest już nieaktualna. Istnieją 2 ważne zmiany, od wersji EF 4.1 klasa ModelBuilder ma teraz nazwę DbModelBuilder, a obecnie istnieje metoda DecimalPropertyConfiguration.HasPrecision, która ma sygnaturę:
gdzie precyzja jest całkowitą liczbą cyfr, które baza danych będzie przechowywać, niezależnie od tego, gdzie spada kropka dziesiętna, a skala jest liczbą miejsc dziesiętnych, które zapisze.
Dlatego nie ma potrzeby powtarzania właściwości, jak pokazano, ale można po prostu wywołać z
źródło
System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder
base.OnModelCreating(modelBuilder);
. Czy była to celowa czy tylko ofiara pisania kodu online zamiast w IDE?Jeśli chcesz ustawić dokładność dla wszystkich
decimals
w EF6, możesz zastąpić domyślnąDecimalPropertyConvention
konwencję używaną wDbModelBuilder
:Domyślnie
DecimalPropertyConvention
w EF6 odwzorowujedecimal
właściwości nadecimal(18,2)
kolumny.Jeśli chcesz, aby poszczególne właściwości miały określoną dokładność, możesz ustawić dokładność właściwości encji na
DbModelBuilder
:Lub dodaj
EntityTypeConfiguration<>
dla encji, która określa precyzję:źródło
Miło spędziłem czas, tworząc niestandardowy atrybut dla tego:
używając tego w ten sposób
a magia dzieje się przy tworzeniu modelu z pewnym odbiciem
pierwsza część polega na uzyskaniu wszystkich klas w modelu (mój niestandardowy atrybut jest zdefiniowany w tym zestawie, więc użyłem go, aby uzyskać zestaw z modelem)
drugi foreach otrzymuje wszystkie właściwości w tej klasie z atrybutem niestandardowym, a sam atrybut, dzięki czemu mogę uzyskać dokładność i skalować dane
potem muszę zadzwonić
więc wywołuję modelBuilder.Entity () przez odbicie i zapisuję go w zmiennej entityConfig, a następnie buduję wyrażenie lambda „c => c.PROPERTY_NAME”
Następnie, jeśli liczba dziesiętna jest zerowalna, wywołuję
metoda (nazywam to pozycją w tablicy, nie jest to idealne, wiem, każda pomoc będzie mile widziana)
a jeśli nie jest to zerowalne, dzwonię pod numer
metoda.
Mając DecimalPropertyConfiguration wywołuję metodę HasPrecision.
źródło
MethodInfo methodInfo = entityConfig.GetType().GetMethod("Property", new[] { lambdaExpression.GetType() });
aby uzyskać prawidłowe przeciążenie. wydaje się działać do tej pory.Używając
DecimalPrecisonAttribute
z KinSlayerUY, w EF6 możesz stworzyć konwencję, która będzie obsługiwać poszczególne właściwości, które mają atrybut (w przeciwieństwie do ustawianiaDecimalPropertyConvention
podobnych w tej odpowiedzi, które wpłyną na wszystkie właściwości dziesiętne).Następnie w
DbContext
:źródło
Precision
, zalecamy ustawienie górnej granicy na 28 (więc> 28
w twoim stanie). Zgodnie z dokumentacją MSDNSystem.Decimal
może reprezentować maksymalnie 28-29 cyfr precyzji ( msdn.microsoft.com/en-us/library/364x0z75.aspx ). Ponadto atrybut określaScale
jakobyte
, co oznacza, że warunek wstępnyattribute.Scale < 0
jest niepotrzebny.System.Decimal
nie. Dlatego nie ma sensu ustawiać górnej granicy warunku na wartość większą niż 28;System.Decimal
najwyraźniej nie mogą reprezentować tak dużych liczb. Należy również pamiętać, że ten atrybut jest przydatny dla dostawców danych innych niż SQL Server. Na przykładnumeric
typ PostgreSQL obsługuje do 131072 cyfr dokładności.decimal(38,9)
kolumna z przyjemnością przytrzyma,System.Decimal.MaxValue
aledecimal(28,9)
kolumna nie. Nie ma powodu, aby ograniczać precyzję tylko do 28.Najwyraźniej możesz przesłonić metodę DbContext.OnModelCreating () i skonfigurować dokładność w następujący sposób:
Ale jest to dość żmudny kod, gdy musisz to zrobić ze wszystkimi swoimi właściwościami związanymi z ceną, więc wymyśliłem to:
Dobrą praktyką jest wywoływanie metody podstawowej, gdy zastępujesz metodę, nawet jeśli implementacja podstawowa nic nie robi.
Aktualizacja: ten artykuł był również bardzo pomocny.
źródło
base.OnModelCreating(modelBuilder);
było konieczne. Z metadanych DbContext w 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 Ver 6 (Alpha, rc1) ma coś o nazwie Konwencje niestandardowe . Aby ustawić dokładność dziesiętną:
Odniesienie:
źródło
będzie to działać z pierwszymi migracjami kodu EF Core, jak opisano tutaj .
źródło
The store type 'decimal(18,2)' could not be found in the SqlServer provider manifest
ta linia kodu może być prostszym sposobem na osiągnięcie tego samego:
źródło
- DLA EF CORE - przy użyciu System.ComponentModel.DataAnnotations;
use
[Column
(TypeName
= "decimal
( precyzja , skala )")]
Precyzja = całkowita liczba użytych znaków
Skala = całkowita liczba po kropce. (łatwo się pomylić)
Przykład :
Więcej informacji tutaj: https://docs.microsoft.com/en-us/ef/core/modeling/relational/data-types
źródło
W EF6
źródło
Zawsze możesz powiedzieć EF, aby zrobił to z konwencjami w klasie Context w funkcji OnModelCreating w następujący sposób:
Dotyczy to tylko Code First EF fyi i dotyczy wszystkich typów dziesiętnych odwzorowanych na db.
źródło
Remove<DecimalPropertyConvention>();
nadejdzieAdd(new DecimalPropertyConvention(18, 4));
. Myślę, że to dziwne, że nie jest po prostu automatycznie zastępowane.Za pomocą
Możesz po prostu umieścić ten atrybut w swoim modelu:
źródło
Więcej informacji na temat MSDN - aspekt Entity Data Model. http://msdn.microsoft.com/en-us/library/ee382834.aspx Pełna rekomendacja.
źródło
Rzeczywiste dla EntityFrameworkCore 3.1.3:
jakieś rozwiązanie w OnModelCreating:
źródło
Niestandardowy atrybut KinSlayerUY działał dla mnie dobrze, ale miałem problemy ze ComplexTypes. Były one mapowane jako byty w kodzie atrybutu, więc nie mogły być następnie mapowane jako ComplexType.
Dlatego rozszerzyłem kod, aby to umożliwić:
źródło
@ Mark007, zmieniłem kryteria wyboru typu, aby uzyskać dostęp do właściwości DbSet <> DbContext. Myślę, że jest to bezpieczniejsze, ponieważ zdarza się, że w podanej przestrzeni nazw istnieją klasy, które nie powinny być częścią definicji modelu lub są, ale nie są jednostkami. Albo twoje byty mogą znajdować się w oddzielnych przestrzeniach nazw lub osobnych zestawach i być połączone razem w jeden Kontekst.
Ponadto, choć mało prawdopodobne, nie sądzę, że można bezpiecznie polegać na porządkowaniu definicji metod, dlatego lepiej jest wyciągać je według listy parametrów. (.GetTypeMethods () to metoda rozszerzenia, którą zbudowałem do pracy z nowym paradygmatem TypeInfo i może spłaszczać hierarchie klas podczas wyszukiwania metod).
Należy pamiętać, że OnModelCreating deleguje do tej metody:
źródło