EF कोड प्रथम में दशमलव सटीक और पैमाना


230

मैं इस कोड-प्रथम दृष्टिकोण के साथ प्रयोग कर रहा हूं, लेकिन मुझे अब पता चला है कि प्रकार System.Decimal की एक संपत्ति टाइप दशमलव (18, 0) के एक वर्ग कॉलम में मैप की जाती है।

मैं डेटाबेस कॉलम की शुद्धता कैसे निर्धारित करूं?


11
एक तरीका [Column(TypeName = "decimal(18,4)")]आपके दशमलव गुणों के लिए विशेषता का उपयोग करना है
S.Serpooshan

[कॉलम (टाइपनाम = "दशमलव (१ ",४)")] महान काम किया !!!
ब्रायन राइस

जवाबों:


257

डेव वान डेन आईंडी का जवाब अब पुराना हो गया है। EF 4.1 से 2 महत्वपूर्ण परिवर्तन हुए हैं, बाद में ModelBuilder वर्ग DbModelBuilder है और अब एक DecimalPropertyConfiguration.HasPreaches विधि है जिस पर हस्ताक्षर हैं:

public DecimalPropertyConfiguration HasPrecision(
byte precision,
byte scale )

जहाँ सटीकता अंक की कुल संख्या है db स्टोर करेगा, चाहे दशमलव बिंदु कहाँ गिरे और पैमाने दशमलव स्थानों की संख्या है जो इसे संग्रहीत करेगा।

इसलिए दिखाए गए गुणों के माध्यम से पुनरावृति करने की आवश्यकता नहीं है, लेकिन बस से बुलाया जा सकता है

public class EFDbContext : DbContext
{
   protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
   {
       modelBuilder.Entity<Class>().Property(object => object.property).HasPrecision(12, 10);

       base.OnModelCreating(modelBuilder);
   }
}

DbModelBuilder के साथ समस्या हो रही है किसी के लिए, कोशिश करेंSystem.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder
लॉयड पॉवेल

1
मैंने देखा कि आपने कभी फोन नहीं किया base.OnModelCreating(modelBuilder);। क्या वह जानबूझकर या सिर्फ आईडीई के बजाय ऑनलाइन टाइपिंग कोड का शिकार था?
बेनस्वेने

1
@BenSwayne मौके के लिए धन्यवाद, यह मेरी चूक है, कुछ भी जानबूझकर नहीं। मैं जवाब को संपादित करूंगा।
एलेक्सा ऑग

26
हस्प्रेटिश (परिशुद्धता, स्केल) के 2 तर्क खराब दस्तावेज हैं। परिशुद्धता वह अंकों की कुल संख्या है जिसे वह संग्रहीत करेगा, चाहे दशमलव बिंदु जहां भी गिरे। स्केल दशमलव स्थानों की संख्या है जो इसे संग्रहीत करेगा।
क्रिस मोसचिनी

1
क्या सभी स्थानों पर सभी दशमलव संपत्तियों के लिए इसे एक ही स्थान पर सेट करने के लिए एक EF कॉन्फ़िगरेशन है? हम आम तौर पर (19,4) का उपयोग करते हैं। यह अच्छा होगा कि यह स्वचालित रूप से सभी दशमलव गुणों पर लागू हो, इसलिए हम एक संपत्ति परिशुद्धता और गणना में प्रत्याशित परिशुद्धता को याद नहीं कर सकते।
माइक डी क्लार्क

89

यदि आप decimalsEF6 में सभी के लिए सटीक सेट करना चाहते हैं, तो आप इसमें DecimalPropertyConventionप्रयुक्त डिफ़ॉल्ट सम्मेलन को बदल सकते हैं DbModelBuilder:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<DecimalPropertyConvention>();
    modelBuilder.Conventions.Add(new DecimalPropertyConvention(38, 18));
}

DecimalPropertyConventionEF6 में डिफ़ॉल्ट स्तंभों के decimalलिए गुण मैप करता decimal(18,2)है।

यदि आप केवल व्यक्तिगत गुणों के लिए एक निर्दिष्ट परिशुद्धता चाहते हैं तो आप इकाई की संपत्ति के लिए सटीक सेट कर सकते हैं DbModelBuilder:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>().Property(e => e.Value).HasPrecision(38, 18);
}

या, EntityTypeConfiguration<>उस इकाई के लिए जोड़ें जो सटीकता निर्दिष्ट करती है:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new MyEntityConfiguration());
}

internal class MyEntityConfiguration : EntityTypeConfiguration<MyEntity>
{
    internal MyEntityConfiguration()
    {
        this.Property(e => e.Value).HasPrecision(38, 18);
    }
}

1
मेरा पसंदीदा समाधान। CodeFirst और माइग्रेशन का उपयोग करते समय सही काम करता है: EF उन सभी वर्गों में सभी गुणों की तलाश करता है जहां "दशमलव" का उपयोग किया जाता है और इन गुणों के लिए माइग्रेशन उत्पन्न करता है। महान!
ओकिह

75

मेरे पास इसके लिए एक कस्टम विशेषता बनाने का अच्छा समय था:

[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; }

}

इस तरह का उपयोग कर

[DecimalPrecision(20,10)]
public Nullable<decimal> DeliveryPrice { get; set; }

और जादू कुछ प्रतिबिंब के साथ मॉडल निर्माण पर होता है

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

पहला भाग मॉडल में सभी वर्गों को प्राप्त करने के लिए है (मेरी कस्टम विशेषता उस विधानसभा में परिभाषित की गई है, इसलिए मैंने इसका उपयोग मॉडल के साथ विधानसभा प्राप्त करने के लिए किया है)

दूसरी विशेषता के साथ उस वर्ग में सभी गुण प्राप्त हो जाते हैं, और वह विशेषता जिसे मैं स्वयं सटीक और स्केल डेटा प्राप्त कर सकता हूं

उसके बाद मुझे फोन करना होगा

modelBuilder.Entity<MODEL_CLASS>().Property(c=> c.PROPERTY_NAME).HasPrecision(PRECISION,SCALE);

इसलिए मैं प्रतिबिंब द्वारा मॉडलबेल्ट.इंटिटी () को कॉल करता हूं और इसे एंटीकॉनगिग चर में संग्रहीत करता हूं, फिर मैं "c => c.PROPERTY_NAME" लंबो एक्सप्रेशन बनाता हूं

उसके बाद, यदि दशमलव अशक्त है, तो मैं कॉल करता हूं

Property(Expression<Func<TStructuralType, decimal?>> propertyExpression) 

विधि (मैं इसे सरणी में स्थिति से कहता हूं, यह आदर्श नहीं है मुझे पता है, किसी भी मदद की बहुत सराहना की जाएगी)

और अगर यह अशक्त नहीं है तो मैं फोन करता हूं

Property(Expression<Func<TStructuralType, decimal>> propertyExpression)

तरीका।

DecimalPropertyConfiguration होने के बाद मैं HasPreults विधि कहता हूं।


3
इसके लिए धन्यवाद। इसने मुझे हज़ारों लंबोदर भाव उत्पन्न करने से बचाया।
शॉन

1
यह महान काम करता है, और सुपर साफ है! EF 5 के लिए, मैंने System.Data.Entity.ModelConfiguration.odelBuilder को System.Data.Entity.DbModelBuilder
Colin

3
मैं MethodInfo methodInfo = entityConfig.GetType().GetMethod("Property", new[] { lambdaExpression.GetType() });सही अधिभार प्राप्त करने के लिए उपयोग करता हूं । अभी तक तो काम कर रहा है।
fscan

3
मैंने इसे एक लाइब्रेरी में लपेट दिया है और DbContext से कॉल करना आसान बना दिया है: github.com/richardlawley/EntityFrameworkAttributeConfig (भी nuget के माध्यम से उपलब्ध)
रिचर्ड

रिचर्ड, मैं आपके प्रोजेक्ट के विचार से प्यार करता हूं, लेकिन क्या इसके बारे में ऐसा कुछ है जिसे EF6 की आवश्यकता है? यदि कोई EF5- संगत संस्करण था, तो मैं इसका उपयोग करूंगा, ताकि मैं इसे ODP.NET के अपने संस्करण के साथ उपयोग कर सकूं।
पैट्रिक सज्जापस्की

50

का उपयोग करते हुए DecimalPrecisonAttribute KinSlayerUY से, EF6 में आप एक सम्मेलन जो अलग-अलग प्रॉपर्टी जो विशेषता है (के रूप में स्थापित करने के लिए विरोध संभाल लेंगे बना सकते हैं DecimalPropertyConventionकी तरह इस जवाब जो सभी दशमलव गुणों को प्रभावित करेगा)।

[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; }
}

public class DecimalPrecisionAttributeConvention
    : PrimitivePropertyAttributeConfigurationConvention<DecimalPrecisionAttribute>
{
    public override void Apply(ConventionPrimitivePropertyConfiguration configuration, DecimalPrecisionAttribute attribute)
    {
        if (attribute.Precision < 1 || attribute.Precision > 38)
        {
            throw new InvalidOperationException("Precision must be between 1 and 38.");
        }

        if (attribute.Scale > attribute.Precision)
        {
            throw new InvalidOperationException("Scale must be between 0 and the Precision value.");
        }

        configuration.HasPrecision(attribute.Precision, attribute.Scale);
    }
}

फिर अपने में DbContext:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());
}

@MichaelEdenfield वास्तव में कोई भी EF6 में इनमें से एक नहीं है। इसलिए मैंने दो उत्तर जोड़े, यह एक और दूसरा जिसे आपने संदर्भित किया है। यह एक विशेषता है जिसे आप मॉडल में सभी दशमलव गुणों को प्रभावित करने के बजाय एकल दशमलव संपत्ति पर रख सकते हैं।
kjbartel

\: मेरा बुरा, नोटिस नहीं आप उन दोनों को लिखा था
माइकल Edenfield

1
यदि आप सीमा-जांच करने जा रहे हैं Precision, तो मैं ऊपरी 28 को बाध्य करने की सलाह देता हूं (इसलिए > 28आपकी स्थिति में)। MSDN प्रलेखन के अनुसार, System.Decimalकेवल परिशुद्धता के अधिकतम 28-29 अंक का प्रतिनिधित्व कर सकते हैं ( msdn.microsoft.com/en-us/library/364x0z75.aspx )। इसके अलावा, विशेषता के Scaleरूप में घोषित किया जाता है byte, जिसका अर्थ है कि आपकी पूर्व शर्त attribute.Scale < 0अनावश्यक है।
नाथनअल्डनश्री

2
@kjbartel यह सच है कि कुछ डेटाबेस प्रदाता 28 से बड़े पूर्वाग्रहों का समर्थन करते हैं; हालाँकि, MSDN के अनुसार System.Decimalनहीं है। इसलिए यह 28 से अधिक के लिए ऊपरी बाध्य पूर्व शर्त सेट करने के लिए कोई मतलब नहीं है; System.Decimalजाहिर है कि बड़ी संख्या का प्रतिनिधित्व नहीं कर सकते। यह भी जान लें कि यह विशेषता SQL सर्वर के अलावा डेटा प्रदाताओं के लिए उपयोगी है। उदाहरण के लिए, PostgreSQL का numericप्रकार परिशुद्धता के 131072 अंकों तक का समर्थन करता है।
नेथन एल्डन

1
@NathanAldenSr जैसा मैंने कहा, डेटाबेस एक निश्चित बिंदु दशमलव ( msdn ) का उपयोग करता है जबकि System.Decimal फ्लोटिंग पॉइंट है । वे पूरी तरह से अलग हैं। उदाहरण के लिए एक decimal(38,9)कॉलम होने से खुशी होगी System.Decimal.MaxValueलेकिन एक decimal(28,9)कॉलम नहीं होगा। परिशुद्धता को केवल 28 तक सीमित करने का कोई कारण नहीं है।
kjbartel

47

जाहिरा तौर पर, आप DbContext.OnModelCreating () विधि को ओवरराइड कर सकते हैं और इस तरह परिशुद्धता को कॉन्फ़िगर कर सकते हैं:

protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>().Property(product => product.Price).Precision = 10;
    modelBuilder.Entity<Product>().Property(product => product.Price).Scale = 2;
}

लेकिन यह बहुत थकाऊ कोड है जब आपको इसे अपने सभी मूल्य-संबंधित गुणों के साथ करना होता है, तो मैं इसके साथ आया:

    protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
    {
        var properties = new[]
        {
            modelBuilder.Entity<Product>().Property(product => product.Price),
            modelBuilder.Entity<Order>().Property(order => order.OrderTotal),
            modelBuilder.Entity<OrderDetail>().Property(detail => detail.Total),
            modelBuilder.Entity<Option>().Property(option => option.Price)
        };

        properties.ToList().ForEach(property =>
        {
            property.Precision = 10;
            property.Scale = 2;
        });

        base.OnModelCreating(modelBuilder);
    }

यह अच्छा अभ्यास है कि जब आप किसी विधि को ओवरराइड करते हैं, तो आधार विधि को कॉल करते हैं, भले ही आधार कार्यान्वयन कुछ भी नहीं करता है।

अद्यतन: यह लेख भी बहुत उपयोगी था।


10
धन्यवाद, इसने मुझे सही दिशा में इशारा किया। CTP5 में एक ही बयान में परिशुद्धता और स्केल को जोड़ने की अनुमति देने के लिए सिंटैक्स बदल गया है: modelBuilder.Entity <Product> ()। संपत्ति (उत्पाद => उत्पाद।) ।HasPreaches (6, 2);
कर्नल

2
फिर भी, यह अच्छा नहीं होगा कि आप सभी डिफ़ॉल्ट के लिए "डिफ़ॉल्ट" के कुछ प्रकार सेट कर सकें ?
डेव वान ने आइंड

3
मुझे नहीं लगता कि कॉल base.OnModelCreating(modelBuilder);करना आवश्यक है। VSB में DbContext मेटाडेटा से: 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.
मैट जेनकिन्स

@ मैट: यह अच्छा है, लेकिन एक कार्यान्वयनकर्ता के रूप में मुझे इस बारे में परवाह नहीं करनी चाहिए और हमेशा आधार को कॉल करना चाहिए।
डेव वान डेन आईंड जूल

@ डेव और @मैट: आधार को कॉल करने के लिए "महत्वपूर्ण" टिप्पणी थी। यह अच्छा अभ्यास है, लेकिन जब ईएफ स्रोत का खाली कार्यान्वयन होता है, तो यह दावा करना भ्रामक है कि यह महत्वपूर्ण है। यह सोचकर लोगों को आश्चर्य होता है कि आधार क्या करता है। मैं बहुत उत्सुक था कि क्या महत्वपूर्ण था मैं जांच करने के लिए ef5.0 से विघटित हो गया। वहां कुछ भी नहीं है। तो बस एक अच्छी आदत।
दार सोड़ी

30

एंटिटी फ्रेमवर्क वेर 6 (अल्फा, आरसी 1) में कस्टम कन्वेंशन नामक कुछ है । दशमलव सटीक सेट करने के लिए:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<decimal>().Configure(config => config.HasPrecision(18, 4));
}

संदर्भ:


22
[Column(TypeName = "decimal(18,2)")]

यह यहाँ वर्णित के रूप में EF कोर कोड पहले पलायन के साथ काम करेगा ।


1
यदि आप इसे अपने मॉडल में जोड़ते हैं, तो आप प्राप्त कर सकते हैंThe store type 'decimal(18,2)' could not be found in the SqlServer provider manifest
Savage

@ सैवेज ऐसा लगता है कि यह आपके डेटाबेस प्रदाता या डेटाबेस के संस्करण के साथ एक समस्या है
एल्नूर

@ इल्नूर सैवेज सही है, यह ईएफ माइग्रेशन 6.x में एक त्रुटि फेंक देगा। विरासत, गैर-कोर संस्करण कॉलम विशेषता के माध्यम से सटीक / पैमाने को निर्दिष्ट करने का समर्थन नहीं करता है, और यदि आप डेटा टाइप विशेषता का उपयोग करते हैं तो कुछ भी नहीं (18,2 तक चूक) करता है। EF 6.x में एट्रीब्यूट के माध्यम से काम करने के लिए, आपको ModelBuilder में अपना खुद का एक्सटेंशन लागू करना होगा।
क्रिस मोसचिनी

1
@ क्रिसमोसचिनी, मैंने EF Core का उल्लेख करते हुए अपना उत्तर बदल दिया। धन्यवाद
Elnoor

14

इस कोड लाइन को सरल बनाने का एक सरल तरीका हो सकता है:

 public class ProductConfiguration : EntityTypeConfiguration<Product>
    {
        public ProductConfiguration()
        {
            this.Property(m => m.Price).HasPrecision(10, 2);
        }
    }

9

- एफई कोर के लिए - के साथ System.ComponentModel.DataAnnotations का उपयोग करने के ;

उपयोग [Column( TypeName = "decimal( परिशुद्धता , पैमाने )")]

सटीक = कुल वर्णों की संख्या

स्केल = डॉट के बाद की कुल संख्या। (भ्रमित होने में आसान)

उदाहरण :

public class Blog
{
    public int BlogId { get; set; }
    [Column(TypeName = "varchar(200)")]
    public string Url { get; set; }
    [Column(TypeName = "decimal(5, 2)")]
    public decimal Rating { get; set; }
}

अधिक विवरण यहां: https://docs.microsoft.com/en-us/ef/core/modeling/relational/data-tpes


3

ईएफ 6 में

modelBuilder.Properties()
    .Where(x => x.GetCustomAttributes(false).OfType<DecimalPrecisionAttribute>().Any())
    .Configure(c => {
        var attr = (DecimalPrecisionAttribute)c.ClrPropertyInfo.GetCustomAttributes(typeof (DecimalPrecisionAttribute), true).FirstOrDefault();

        c.HasPrecision(attr.Precision, attr.Scale);
    });

यह उत्तर किसी अन्य उत्तर के उन्नयन के लिए लगता है जो विशेषता को परिभाषित करता है, आपको इसे उस उत्तर में संपादित करना चाहिए
Rhys Bevilaqua

3

आप हमेशा EF को OnModelCreating फ़ंक्शन में संदर्भ वर्ग में सम्मेलनों के साथ ऐसा करने के लिए कह सकते हैं:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // <... other configurations ...>
    // modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    // modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
    // modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

    // Configure Decimal to always have a precision of 18 and a scale of 4
    modelBuilder.Conventions.Remove<DecimalPropertyConvention>();
    modelBuilder.Conventions.Add(new DecimalPropertyConvention(18, 4));

    base.OnModelCreating(modelBuilder);
}

यह केवल कोड फर्स्ट EF फी पर लागू होता है और db पर मैप किए गए सभी दशमलव प्रकारों पर लागू होता है।


इससे Remove<DecimalPropertyConvention>();पहले तक काम नहीं कर रहा था Add(new DecimalPropertyConvention(18, 4));। मुझे लगता है कि यह अजीब है जो सिर्फ स्वचालित रूप से ओवरराइड नहीं है।
माइक डी किलक

2

का उपयोग करते हुए

System.ComponentModel.DataAnnotations;

आप बस उस विशेषता को अपने मॉडल में डाल सकते हैं:

[DataType("decimal(18,5)")]

1
यह पठनीयता और सरलता के लिए सबसे आसान कार्यान्वयन है। IMHO
ransems

11
प्रति msdn.microsoft.com/en-us/library/jj591583(v=vs.113).aspx , यह उत्तर तथ्यात्मक रूप से गलत है। "DataType DataAnnotation के साथ Column के TypeName विशेषता को भ्रमित न करें। DataType UI के लिए उपयोग किया जाने वाला एक एनोटेशन है और इसे Code First द्वारा अनदेखा किया जाता है।"
speckledcarp

2
@ransems मैंने भी ऐसा सोचा था, जब तक कि मैंने अभी इसका परीक्षण नहीं किया था और जैसा कि ऊपर कहा गया था, यह कोडफ़र्स्ट के लिए काम नहीं करता है और डेटाबेस में नहीं जाता है
RoLYroLLs

1

आप MSDN - Entity Data Model के पहलू पर अधिक जानकारी प्राप्त कर सकते हैं। http://msdn.microsoft.com/en-us/library/ee382834.aspx पूर्ण अनुशंसित।


यह बहुत अच्छा है और सभी, लेकिन यह कोड-प्रथम से कैसे संबंधित है?
डेव वान डेन आइंड

यह उपयोगी है, लेकिन मैं अभी भी एक दशमलव के लिए [परिशुद्धता] विशेषता निर्दिष्ट नहीं कर सकता। इसलिए मैंने @KinSlayerUY द्वारा प्रदान किए गए समाधान का उपयोग किया।
कॉलिन

1

EntityFrameworkCore 3.1.3 के लिए वास्तविक:

OnModelCreating में कुछ समाधान:

var fixDecimalDatas = new List<Tuple<Type, Type, string>>();
foreach (var entityType in builder.Model.GetEntityTypes())
{
    foreach (var property in entityType.GetProperties())
    {
        if (Type.GetTypeCode(property.ClrType) == TypeCode.Decimal)
        {
            fixDecimalDatas.Add(new Tuple<Type, Type, string>(entityType.ClrType, property.ClrType, property.GetColumnName()));
        }
    }
}

foreach (var item in fixDecimalDatas)
{
    builder.Entity(item.Item1).Property(item.Item2, item.Item3).HasColumnType("decimal(18,4)");
}

//custom decimal nullable:
builder.Entity<SomePerfectEntity>().Property(x => x.IsBeautiful).HasColumnType("decimal(18,4)");

0

KinSlayerUY की कस्टम विशेषता ने मेरे लिए अच्छी तरह से काम किया लेकिन मेरे पास ComplexTypes के साथ समस्याएँ थीं। उन्हें विशेषता कोड में संस्थाओं के रूप में मैप किया जा रहा था, इसलिए उन्हें कॉम्प्लेक्स टाइप के रूप में मैप नहीं किया जा सकता था।

इसलिए मैंने इसके लिए अनुमति देने के लिए कोड बढ़ाया:

public static void OnModelCreating(DbModelBuilder modelBuilder)
    {
        foreach (Type classType in from t in Assembly.GetAssembly(typeof(DecimalPrecisionAttribute)).GetTypes()
                                   where t.IsClass && t.Namespace == "FA.f1rstval.Data"
                                   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) }))
            {

                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;
                int MethodNum;
                if (propAttr.prop.PropertyType.IsGenericType && propAttr.prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    MethodNum = 7;
                }
                else
                {
                    MethodNum = 6;
                }

                //check if complextype
                if (classType.GetCustomAttribute<ComplexTypeAttribute>() != null)
                {
                    var complexConfig = modelBuilder.GetType().GetMethod("ComplexType").MakeGenericMethod(classType).Invoke(modelBuilder, null);
                    MethodInfo methodInfo = complexConfig.GetType().GetMethods().Where(p => p.Name == "Property").ToList()[MethodNum];
                    decimalConfig = methodInfo.Invoke(complexConfig, new[] { lambdaExpression }) as DecimalPropertyConfiguration;
                }
                else
                {
                    var entityConfig = modelBuilder.GetType().GetMethod("Entity").MakeGenericMethod(classType).Invoke(modelBuilder, null);
                    MethodInfo methodInfo = entityConfig.GetType().GetMethods().Where(p => p.Name == "Property").ToList()[MethodNum];
                    decimalConfig = methodInfo.Invoke(entityConfig, new[] { lambdaExpression }) as DecimalPropertyConfiguration;
                }

                decimalConfig.HasPrecision(propAttr.attr.Precision, propAttr.attr.Scale);
            }
        }
    }

0

@ Mark007, मैंने DbCettext के DbSet <> गुणों की सवारी करने के लिए चयन के प्रकार को बदल दिया है। मुझे लगता है कि यह सुरक्षित है क्योंकि कई बार आपके पास दिए गए नेमस्पेस में ऐसी कक्षाएं होती हैं जो मॉडल की परिभाषा का हिस्सा नहीं होनी चाहिए या वे नहीं हैं, लेकिन संस्थाएं नहीं हैं। या आपकी संस्थाएँ अलग-अलग नामस्थान या अलग-अलग विधानसभाओं में निवास कर सकती हैं और एक साथ एक बार प्रसंग में खींची जा सकती हैं।

इसके अलावा, भले ही संभावना नहीं है, मुझे नहीं लगता कि विधि परिभाषाओं के आदेश पर भरोसा करना सुरक्षित है, इसलिए उन्हें व्यास सूची से बाहर निकालना बेहतर है। (.GetTypeMethods () एक एक्सटेंशन विधि है जिसे मैंने नए TypeInfo प्रतिमान के साथ काम करने के लिए बनाया है और तरीकों की तलाश में वर्ग पदानुक्रम को समतल कर सकता है)।

ध्यान दें कि OnModelCreating प्रतिनिधियों को इस विधि में:

    private void OnModelCreatingSetDecimalPrecisionFromAttribute(DbModelBuilder modelBuilder)
    {
        foreach (var iSetProp in this.GetType().GetTypeProperties(true))
        {
            if (iSetProp.PropertyType.IsGenericType
                    && (iSetProp.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>) || iSetProp.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)))
            {
                var entityType = iSetProp.PropertyType.GetGenericArguments()[0];

                foreach (var propAttr in entityType
                                        .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                        .Select(p => new { prop = p, attr = p.GetCustomAttribute<DecimalPrecisionAttribute>(true) })
                                        .Where(propAttr => propAttr.attr != null))
                {
                    var entityTypeConfigMethod = modelBuilder.GetType().GetTypeInfo().DeclaredMethods.First(m => m.Name == "Entity");
                    var entityTypeConfig = entityTypeConfigMethod.MakeGenericMethod(entityType).Invoke(modelBuilder, null);

                    var param = ParameterExpression.Parameter(entityType, "c");
                    var lambdaExpression = Expression.Lambda(Expression.Property(param, propAttr.prop.Name), true, new ParameterExpression[] { param });

                    var propertyConfigMethod =
                        entityTypeConfig.GetType()
                            .GetTypeMethods(true, false)
                            .First(m =>
                            {
                                if (m.Name != "Property")
                                    return false;

                                var methodParams = m.GetParameters();

                                return methodParams.Length == 1 && methodParams[0].ParameterType == lambdaExpression.GetType();
                            }
                            );

                    var decimalConfig = propertyConfigMethod.Invoke(entityTypeConfig, new[] { lambdaExpression }) as DecimalPropertyConfiguration;

                    decimalConfig.HasPrecision(propAttr.attr.Precision, propAttr.attr.Scale);
                }
            }
        }
    }



    public static IEnumerable<MethodInfo> GetTypeMethods(this Type typeToQuery, bool flattenHierarchy, bool? staticMembers)
    {
        var typeInfo = typeToQuery.GetTypeInfo();

        foreach (var iField in typeInfo.DeclaredMethods.Where(fi => staticMembers == null || fi.IsStatic == staticMembers))
            yield return iField;

        //this bit is just for StaticFields so we pass flag to flattenHierarchy and for the purpose of recursion, restrictStatic = false
        if (flattenHierarchy == true)
        {
            var baseType = typeInfo.BaseType;

            if ((baseType != null) && (baseType != typeof(object)))
            {
                foreach (var iField in baseType.GetTypeMethods(true, staticMembers))
                    yield return iField;
            }
        }
    }

मुझे बस एहसास हुआ कि मैं इस दृष्टिकोण से ComplexTypes से नहीं निपटता। इसे बाद में संशोधित करेंगे।
एनियोला

हालांकि, ब्रायन द्वारा प्रस्तावित समाधान सरल, सुरुचिपूर्ण और काम करता है। मैं प्रदर्शन के बारे में कोई स्पष्ट बयान नहीं दूंगा लेकिन अपनी शिकार करने की बजाय पहले से ही दिखाई गई प्रॉपर्टीइंफो पर सवारी करने से आपको बहुत बड़े मॉडल (200 और ऊपर के क्रम में) पर बेहतर प्रदर्शन करना चाहिए।
एनियोला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.