#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 — Егор — ты молодец! Это сработало, и я целую вечность искал, как сделать что-то вроде этого лямбда-выражения. Я поддержу вас в вашем другом сообщении, поскольку у меня есть только один отзыв, который я могу дать здесь.