2013-06-04 15 views
22

Moja Model:Niechciane dziesiętny Obcinanie

public class Product 
{ 
    ... 
     public decimal Fineness { get; set; } 
    ... 
} 

Siew bazie danych:

new List<Product> 
     { 
      new Product { ..., Fineness = 0.757M, ... }, 
      new Product { ..., Fineness = 0.674M, ... }, 
      new Product { ..., Fineness = 0.475M, ... } 
     }.ForEach(p => context.Products.Add(p)); 

przeglądając bazę danych w celu przetestowania wysiewu:

var products = db.Products.ToList(); 
foreach (var p in products) 
{ 
    S.D.Debug.WriteLine("ProductList: {0}, {1}", p.Name, p.Fineness); 
} 

konsoli wyjściowa:

ProductList: Test Product, 0.75 
ProductList: Test Product, 0.67 
ProductList: Test Product, 0.47  

Czy robię coś naprawdę głupiego czy coś? Wszystko jest obcinane do 2 miejsc po przecinku.

Solution - Dzięki Patrick:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Product>().Property(x => x.Fineness).HasPrecision(10, 5); 
} 
+3

Czy skonfigurowałeś precyzję w Entity Framework? –

+0

@PatrickMagee - dostałem rozwiązanie. Dziękuję Ci. Zobacz aktualizację, o którą chodzi. – Gravy

+1

@Gravy Należy poprosić Patricka Magee, aby opublikował to jako odpowiedź, abyś mógł to zaakceptować;) –

Odpowiedz

20

Dzięki temu można mieć standardowe modele podmiot zdefiniowany tutaj jest produkt o identyfikatorze i po przecinku, wraz z wszystkim, czego potrzebujesz itp.

public class Product 
{ 
    public int Id { get; set; } 
    public decimal Fineness { get; set; } 
} 

Tak więc zdefiniowałem n initlizer, w którym to przypadku baza danych opuści i ponownie utworzy wszelkie dostarczone informacje, za każdym razem, gdy uruchomię i wykonam moją aplikację, zostanie ona wywołana.

public class Initializer : DropCreateDatabaseAlways<Context> 
{ 
    protected override void Seed(Context context) 
    { 
     // note how i am specifying it here as 4 digits after the decimal point 
     // and for the second one, 3 digits 
     // this is where EF precision must be configured so you can expect 
     // the values you tell EF to save to the db 
     context.Products.Add(new Product() {Id = 1, Fineness = 145.2442m}); 
     context.Products.Add(new Product() {Id = 2, Fineness = 12.341m}); 
    } 
} 

public class Context : DbContext 
{ 
    public IDbSet<Product> Products { get; set; } 

    public Context() 
    { 
     // I always explicitliy define how my EF should run, but this is not needed for the answer i am providing you 
     Configuration.AutoDetectChangesEnabled = true; 
     Configuration.ProxyCreationEnabled = true; 
     Configuration.LazyLoadingEnabled = true; 
     Configuration.ValidateOnSaveEnabled = true; 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     // so here, I am override the model configuration which is what 
     // EF can use in order to set-up the behaviour of how everything 
     // is configured in the database, from associations between 
     // multiple entities and property validation, Null-able, Precision, required fields etc 
     modelBuilder.Configurations.Add(new ProductConfiguration()); 
    } 
} 

public class ProductConfiguration : EntityTypeConfiguration<Product> 
{ 
    public ProductConfiguration() 
    { 
     ToTable("Product"); 
     HasKey(x => x.Id).Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

     // HAS PRECISION. 
     // Enforces how the value is to be stored in the database 
     // Here you can see I set a scale of 3, that's 3 digits after 
     // the decimal. Notice how in my seed method, i gave a product 4 digits! 
     // That means it will NOT save the product with the other trailing digits. 
     Property(x => x.Fineness).HasPrecision(precision: 10, scale: 3); 
    } 
} 

Z eksploratorem obiektów programu SQL Server, mogę wyświetlić mój localdb Przykładowy produkt, który zrobiłem, aby zobaczyć, jak EF skonfigurował moją bazę danych.

enter image description here

[TestFixture] 
public class Tests 
{ 
    [Test] 
    public void Test() 
    { 
     Database.SetInitializer(new Initializer()); 

     using (var ctx = new Context()) 
     { 
      // assert our findings that it is indeed not what we actually specified in the seed method, because of our Entity configuration with HasPrecision. 
      Product product1 = ctx.Products.Find(1); 
      Assert.AreEqual(145.244m, product1.Fineness); 

      Product product2 = ctx.Products.Find(2); 
      Assert.AreEqual(12.341m, product2.Fineness); 
     }   
    } 
} 

Unit Test has run, seeded the db and we asserted our assumption

Dlatego musimy upewnić się, że baza danych nie wie w jaki sposób należy przechowywać naszą wartość dziesiętną, konfigurując nasz podmiot wykorzystując konfigurację modelu budowniczym Entity Framework, przy użyciu FluentApi, możemy ustawić cechy nieruchomości poprzez EntityTypeConfiguration<T>.

+6

To jest niesamowite wyjaśnienie. Jednak samo dodanie do właściwości mapowania (tuż po zapytaniu LINQ) pomogło rozwiązać mój bardzo podobny problem: '.HasPrecision (precyzja: 10, skala: 3);' – user1835017

0

Oto dobry tutorial formatowania liczb dziesiętnych

D.Debug.WriteLine("ProductList: {0}, {1:0.000}", p.Name, p.Fineness); 

// just two decimal places 
String.Format("{0:0.00}", 123.4567);  // "123.46" 
String.Format("{0:0.00}", 123.4);   // "123.40" 
String.Format("{0:0.00}", 123.0);   // "123.00" 

// max. two decimal places 
String.Format("{0:0.##}", 123.4567);  // "123.46" 
String.Format("{0:0.##}", 123.4);   // "123.4" 
String.Format("{0:0.##}", 123.0);   // "123" 

// at least two digits before decimal point 
String.Format("{0:00.0}", 123.4567);  // "123.5" 
String.Format("{0:00.0}", 23.4567);  // "23.5" 
String.Format("{0:00.0}", 3.4567);  // "03.5" 
String.Format("{0:00.0}", -3.4567);  // "-03.5" 

//Zero formatting 
String.Format("{0:0.0}", 0.0);   // "0.0" 
String.Format("{0:0.#}", 0.0);   // "0" 
String.Format("{0:#.0}", 0.0);   // ".0" 
String.Format("{0:#.#}", 0.0);   // "" 
+1

Sprawdzone, dzięki za link naprawdę przydatne ... ale niestety nie moje rozwiązanie. Wygląda na to, że dziesiętny jest obcięty w momencie przechowywania w bazie danych ... wartości teraz pojawiają się jako "0.750", "0.670" i "0.470" na wyjściu konsoli – Gravy