Как проверить свойства основного поля Entity Framework с помощью Fluent Validation

#c# #entity-framework #entity-framework-core #fluentvalidation

#c# #entity-framework #entity-framework-core #fluentvalidation

Вопрос:

Я пытаюсь свериться с .Свойство HasMaxLength из ядра Entity Framework.

Вот пример метода построения модели:

         protected override void OnModelCreating(ModelBuilder modelBuilder)
             {
              modelBuilder.Entity<Address>(entity =>
                 {
              
                  entity.Property(e => e.AddressEmail)
                .IsRequired()
                .HasMaxLength(255)
                .IsUnicode(false)
                .HasDefaultValueSql("('')");
  

Используя мой контекст, я могу найти максимальную длину следующим образом:

   dbContext.Model.FindEntityType(typeof(Address)).FindProperty("AddressEmail").GetMaxLength()
  

Используя Fluent Validation, я могу это сделать:

   RuleFor(Address => Address.AddressEmail).NotNull().MaximumLength(255);
  

Так что это работает, но когда я меняю структуру базы данных, мне приходится обновлять свои валидаторы.

Я пытаюсь понять, как управлять моими правилами Fluent Validation из свойства entity framework MaxLength

Любая помощь была бы очень признательна.

**** Частично работающий способ ввода dbcontext, но я все еще пытаюсь получить правило:

  public AddressValidator(DbContext dbContext)
      {
        Microsoft.EntityFrameworkCore.Metadata.IEntityType et = dbContext.Model.FindEntityType(typeof(Address));

        foreach (var Property in et.GetProperties())
        {
            var maxLength = Property.GetMaxLength();
  ---->>>>> RuleFor(x =>x.{PropertyName})    Invalid but this is the idea
        }
            
  

Комментарии:

1. Рассмотрите возможность использования проверки аннотаций данных. В этом случае вы можете поместить часть своего свойства с пользовательской проверкой в частичный класс.

2. Спасибо, @Sergey — Я начал использовать аннотацию данных, но моя проверка была слишком сложной, и я продолжал получать непреодолимые ошибки, связанные с версиями библиотеки. Это хорошая идея — она просто не будет работать в моей ситуации.

Ответ №1:

Вы можете ввести свой контекст БД в validator, используя код, который вы предоставили ранее. Не уверен, есть ли адаптер, который делает это автоматически

 class MyClassValidator : AbstractValidator<MyClass>
{
    public MyClassValidator(MyDbContext dbContext)
    {
        var maxLength = dbContext.Model.FindEntityType(typeof(MyClass))
            .FindProperty(nameof(MyClass.Data)).GetMaxLength();

        RuleFor(x => x.Data)
            .MaximumLength(maxLength.Value);
    }
}
  

Обновить

Версия, использующая выражения

 class MyClassValidator : AbstractValidator<MyClass>
{
    public MyClassValidator(MyDbContext dbContext)
    {
        var entityType = dbContext.Model.FindEntityType(typeof(MyClass));

        foreach (var property in typeof(MyClass).GetProperties()
            .Where(x => x.PropertyType == typeof(string)))
        {
            var maxLength = entityType
                .FindProperty(property.Name)
                .GetMaxLength();

            if (maxLength.HasValue) 
            {
                var parameter = Expression.Parameter(typeof(MyClass));
                var memberExpression = Expression.Property(parameter, property.Name);
                var lambdaExpression = Expression.Lambda<Func<MyClass, string>>(memberExpression, parameter);

                RuleFor(lambdaExpression)
                    .MaximumLength(maxLength.Value);
            }
        }

    }
}
  

Комментарии:

1. Спасибо за ваш ответ. Это помогло мне пройти большую часть пути. Я добавляю к коду в своем сообщении вашу идею. Проблема заключается в правиле для x.Data, я не могу вставить тип type. Я надеюсь, что вы посмотрите на это и сообщите мне о любых идеях. Спасибо.

2. OMG — Егор — ты молодец! Это сработало, и я целую вечность искал, как сделать что-то вроде этого лямбда-выражения. Я поддержу вас в вашем другом сообщении, поскольку у меня есть только один отзыв, который я могу дать здесь.