Десяткова точність та масштабність в коді EF Перше


230

Я експериментую з цим першим кодовим підходом, але зараз з’ясовую, що властивість типу System.Decimal потрапляє у таблицю sql типу десяткових (18, 0).

Як встановити точність стовпця бази даних?


11
один із способів - використовувати [Column(TypeName = "decimal(18,4)")]атрибут для ваших десяткових властивостей
S.Serpooshan

[Стовпець (TypeName = "десятковий (18,4)")] відмінно працював !!!
Брайан Райс

Відповіді:


257

Відповідь Дейва Ван ден Ейнде зараз застаріла. Є 2 важливі зміни: від EF 4.1 і далі клас ModelBuilder тепер є DbModelBuilder, і тепер існує метод DecimalPropertyConfiguration.HasPrecision, який має підпис:

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);. Це була навмисна чи просто жертва введення коду в Інтернеті замість IDE?
BenSwayne

1
@BenSwayne дякую за місце, це мій упущення, не що-небудь навмисне. Я відредагую відповідь.
AlexC

26
Два аргументи HasPrecision (точність, масштаб) погано зафіксовані. точність - це загальна кількість цифр, яку вона буде зберігати, незалежно від того, де потрапляє десяткова крапка. шкала - кількість десяткових знаків, які вона буде зберігати.
Кріс Москіні

1
Чи є конфігурація EF, щоб встановити її для всіх десяткових властивостей для всіх об'єктів в одному місці? Ми зазвичай використовуємо (19,4). Було б добре, щоб це було автоматично застосовано до всіх десяткових властивостей, тому ми не можемо забути встановити точність властивості та пропустити передбачувану точність у розрахунках.
Майк де Клерк

89

Якщо ви хочете встановити точність для всіх decimalsв EF6, ви можете замінити DecimalPropertyConventionумовний стандарт, який використовується у DbModelBuilder:

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

За замовчуванням DecimalPropertyConventionу EF6 відображається 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 шукає всі властивості у всіх класах, де використовується "десятковий", і генерує міграцію для цих властивостей. Чудово!
okieh

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

Перша частина полягає в тому, щоб отримати всі класи в моделі (мій спеціальний атрибут визначений у цій збірці, тому я використав це для отримання збірки з моделлю)

другий foreach отримує всі властивості цього класу зі спеціальним атрибутом, а сам атрибут, щоб я міг отримати дані про точність та масштабність

після цього я повинен зателефонувати

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

тому я називаю modelBuilder.Entity () за допомогою відображення і зберігаю його у змінній entitConfig, тоді я будую лямбдаський вираз "c => c.PROPERTY_NAME"

Після цього, якщо десятковий знак є нульовим, я закликаю

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

метод (я називаю це позицією в масиві, це не ідеально, я знаю, будь-яка допомога буде дуже вдячна)

і якщо це не є нульовим, я дзвоню на

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

метод.

Маючи DecimalPropertyConfiguration, я викликаю метод HasPrecision.


3
Дякую за це Це врятувало мене від генерації тисяч лямбдаських виразів.
Шон

1
Це чудово працює, і це супер чисто! Для EF 5 я змінив System.Data.Entity.ModelConfiguration.ModelBuilder на System.Data.Entity.DbModelBuilder
Колін

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

мені погано, не помітили, що ви їх написали обом: \
Майкл Еденфілд

1
Якщо ви збираєтесь перевірити межу Precision, то рекомендую встановити верхню межу на 28 (так > 28у вашому стані). Відповідно до документації MSDN, System.Decimalможе представляти максимум 28-29 цифр точності ( msdn.microsoft.com/en-us/library/364x0z75.aspx ). Також атрибут оголошує Scaleяк byte, що означає, що ваша передумова attribute.Scale < 0непотрібна.
NathanAldenSr

2
@kjbartel Це правда, що деякі постачальники баз даних підтримують точніші, що перевищують 28; однак, на думку MSDN, System.Decimalцього немає. Тому немає сенсу встановлювати верхню межу передумови чимось більшим, ніж 28; System.DecimalМабуть, не може представляти великі числа. Також майте на увазі, що цей атрибут корисний для інших постачальників даних, крім SQL Server. Наприклад, numericтип PostgreSQL підтримує до 131072 цифр точності.
NathanAldenSr

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 синтаксис змінився, щоб додати Precision and Scale в один і той же оператор: modelBuilder.Entity <Product> () .Property (product => product.Price) .HasPrecision (6, 2);
Кол

2
Все-таки, чи не було б непогано мати якийсь "за замовчуванням", який можна встановити для всіх десяткових знаків?
Дейв Ван ден Ейнде

3
Я не думаю, що дзвонити base.OnModelCreating(modelBuilder);потрібно. З метаданих DbContext у 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.
Метт Дженкінс

@Matt: Це добре, але як реалізатор я не повинен про це дбати і завжди називати базу.
Дейв Ван ден Ейнде

@ Дейв і @ Матт: Був коментар, що "ВАЖЛИВО" дзвонити на базу. Це добра практика, але коли джерело EF має порожню реалізацію, вводити в оману твердження, що це важливо. Це залишає людей цікавитись, що робить база. Мені було так цікаво, що ВАЖЛИВО я декомпілював на ef5.0, щоб перевірити. Нічого там немає. Тож просто гарна звичка.
phil soady

30

Entity Framework Ver 6 (Alpha, rc1) має щось, що називається Спеціальні конвенції . Щоб встановити десяткову точність:

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

Довідка:


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

це буде працювати з першими міграціями коду EF Core, як описано тут .


1
Якщо ви просто додасте це до своєї моделі, ви можете отриматиThe store type 'decimal(18,2)' could not be found in the SqlServer provider manifest
Savage

@Savage виглядає як проблема з вашим постачальником даних або версією бази даних
Elnoor

@Elnoor Savage правильний, це призведе до помилки в EF Міграції 6.x. Спадкова, не основна версія не підтримує визначення точності / масштабу через атрибут Column, і нічого не робить (за замовчуванням до 18,2), якщо ви використовуєте атрибут DataType. Щоб змусити його працювати через Attribute в EF 6.x, вам потрібно буде реалізувати власне розширення до ModelBuilder.
Кріс Москіні

1
@ChrisMoschini, я змінив свою відповідь, згадуючи EF Core. Спасибі
Elnoor

14

цей рядок коду міг би бути більш простим способом домогтися того ж:

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

9

- ДЛЯ EF CORE - з допомогою 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-types


3

У EF6

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 робити це за допомогою конвенцій класу Context у функції 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);
}

Це стосується лише Code First EF fyi і стосується всіх десяткових типів, відображених на db.


Це не працювало, поки не з'явиться Remove<DecimalPropertyConvention>();до Add(new DecimalPropertyConvention(18, 4));. Я думаю, що дивно, що це не просто переосмислюється автоматично.
Майк де Клерк

2

Використання

System.ComponentModel.DataAnnotations;

Ви можете просто помістити цей атрибут у свою модель:

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

1
це найпростіша реалізація для читабельності та простоти. ІМХО
рансеми

11
За msdn.microsoft.com/en-us/library/jj591583(v=vs.113).aspx , ця відповідь фактично неправильна. "Не плутайте атрибут TypeName стовпця з атрибутом DataType DataAnnotation. DataType - це анотація, яка використовується для інтерфейсу користувача та ігнорується кодом спочатку."
крапчастий

2
@ransems Я теж думав, поки я тільки не перевірив це і, як було сказано вище, це не працює для CodeFirst і не переходить на базу даних
RoLYroLLs

1

Ви можете знайти додаткову інформацію про MSDN - фасетку Entity Data Model. http://msdn.microsoft.com/en-us/library/ee382834.aspx Повна рекомендована.


Це чудово і все, але як це стосується Code-First?
Дейв Ван ден Ейнде

Це корисно, але я не можу вказати атрибут [Precision] для десяткової цифри. Тому я використав рішення, яке надає @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. Їх відображали як сутності в коді атрибутів, тому їх не можна було відобразити як ComplexType.

Тому я розширив код, щоб дозволити це:

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, я змінив критерії вибору типу для керування властивостями DbSet <> DbContext. Я вважаю, що це безпечніше, оскільки у вас є класи у даному просторі імен, які не повинні бути частиною визначення моделі, або вони є, але не є сутностями. Або ваші особи можуть проживати в окремих просторах імен або окремих збірок і бути об'єднаними в один контекст.

Крім того, хоч і малоймовірно, я не думаю, що можна покладатися на впорядкування визначень методів, тому краще витягнути їх за списком параметрів. (.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 таким підходом. Буде переглянути його пізніше.
Еніола

Однак рішення, запропоноване Брайаном , просте, елегантне і працює. Я не буду робити жодних категоричних заяв щодо продуктивності, але їзда вже відбитого PropertyInfo замість того, щоб виганяти вашу, повинна давати кращі показники на дуже великих моделях (порядку 200 і вище).
Еніола
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.