2010-09-20 8 views
2

Как реализовать проверку для сущностных сущностей, когда в определенных ситуациях должна применяться другая логика проверки?Контекстная проверка объектов Entity Framework

Например, подтвердите объект одним способом, если пользователь является администратором, иначе проверьте его другим способом.

+0

Независимо от того, как это называется, как бы вы это сделали? Я хочу, чтобы CONDITIONALLY блокировать сохранение объекта, когда он находится в состоянии INVALID. –

+0

Если вы хотите, чтобы ваша модель находилась в состоянии, когда бизнес считает его действительным, и в этом процессе проверки этой модели вы не изменяете эту модель и не сообщаете о каких-либо ошибках пользователю, в этой ситуации я бы рассмотрите, что вы делаете, это проверка. Неважно, если у вас разные правила для разных пользователей. – Steven

+0

Не забудьте отметить свой любимый ответ ;-) – Steven

ответ

2

Я ставлю проверки атрибутов контекста конкретного, посвященные модели редактирования.

Предприятие имеет только проверки, которые относятся к всем юридическим лицам.

+1

Мне это нравится. Мне не нравится минимальный символ в комментариях. –

1

Пока я не слышал более яркое представление, я делаю это:

public partial class MyObjectContext 
{ 
    ValidationContext ValidationContext { get; set; } 

    partial void OnContextCreated() 
    { 
     SavingChanges += new EventHandler(EntitySavingChanges); 
    } 

    private void EntitySavingChanges(object sender, EventArgs e) 
    { 
     ObjectStateManager 
      .GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted) 
      .Where(entry => entry.Entity is IValidatable).ToList().ForEach(entry => 
      { 
       var entity = entry.Entity as IValidatable; 
       entity.Validate(entry, ValidationContext); 
      }); 
    } 
} 

interface IValidatable 
{ 
    void Validate(ObjectStateEntry entry, ValidationContext context); 
} 

public enum ValidationContext 
{ 
    Admin, 
    SomeOtherContext 
} 

public partial class MyEntity : IValidatable 
{ 
    public ValidationContext ValidationContext { get; set; } 

    public void Validate(ObjectStateEntry entry, ValidationContext context) 
    { 
     // this validation doesn't apply to admins 
     if (context != ValidationContext.Admin) 
     { 
      // validation logic here 
     } 
    } 
} 
2

Прежде чем я начну говорить о том, как это сделать с помощью VAB, позвольте мне сказать, что вам нужно будет действительно подумать о своих правилах проверки. Хотя дифференцирование валидации между ролями возможно, это означает, что объект, который сохраняет пользователь в одной роли, является недопустимым для другого пользователя. Это означает, что пользователю в определенной роли может потребоваться изменить этот объект, прежде чем он сможет его сохранить. Это также может случиться для одного и того же пользователя, когда оно продвигается к другой роли. Если вы уверены в этом, прочитайте.


Это похоже на хорошую работу для предприятия библиотеки Validation Application Block (VAB), так как она позволяет проверять правильность этих сложных сценариев. Когда вы захотите это сделать, забудьте проверить на основе атрибута; это просто не сработает. Для этого вам нужна проверка на основе конфигурации.

Что вы можете использовать с помощью VAB - это использовать файл конфигурации, который содержит фактическую проверку. Это зависит от того, какими должны быть действительные правила проверки, но что вы можете сделать, это создать базовую конфигурацию, которая всегда выполняется для каждого объекта в вашем домене. И затем создайте одну или несколько конфигураций, содержащих только расширенные проверки. Скажем, например, что у вас есть файл validation_base.config, файл validation_manager.config и файл validation_admin.config.

Что вы можете сделать, это объединить эти проверки вместе в зависимости от роли пользователя. Посмотрите, например, на этом примере, что создает три источника конфигурации, на основе файла конфигурации:

var base = new FileConfigurationSource("validation_base.config"); 
var mngr = new FileConfigurationSource("validation_manager.config"); 
var admn = new FileConfigurationSource("validation_admin.config"); 

Теперь вы должны объединить эти файлы в (по крайней мере) две конфигурации. Один из них содержит базовый + менеджер и другой, который содержит правила base + admin. Хотя слияние не является чем-то, что поддерживается из коробки, this article покажет вам, как это сделать. При использовании кода в этой статье, вы будете в состоянии сделать это:

var managerValidations = 
    new ValidationConfigurationSourceCombiner(base, mngr); 

var adminValidations = 
    new ValidationConfigurationSourceCombiner(base, admn); 

Последнее, что вам нужно сделать, это обернуть эти валидации в классе, которые возвращают соответствующий набор на основе роли пользователя , Вы можете, что, как это:

public class RoleConfigurationSource : IConfigurationSource 
{ 
    private IConfigurationSource base; 
    private IConfigurationSource managerValidations; 
    private IConfigurationSource adminValidations; 

    public RoleConfigurationSource() 
    { 
     this.base = new FileConfigurationSource("validation_base.config"); 
     var mngr = new FileConfigurationSource("validation_manager.config"); 
     var admn = new FileConfigurationSource("validation_admin.config"); 

     managerValidations = 
      new ValidationConfigurationSourceCombiner(base, mngr); 

     adminValidations = 
      new ValidationConfigurationSourceCombiner(base, admn); 
    } 

    public ConfigurationSection GetSection(string sectionName) 
    { 
     if (sectionName == ValidationSettings.SectionName) 
     { 
      if (Roles.UserIsInRole("admin")) 
      { 
       return this.adminValidations; 
      } 
      else 
      { 
       return this.managerValidations; 
      } 
     } 

     return null; 
    } 

    #region IConfigurationSource Members 

    // Rest of the IConfigurationSource members left out. 
    // Just implement them by throwing an exception from 
    // their bodies; they are not used. 

    #endregion 
} 

Сейчас этот RoleConfigurationSource может быть создан один раз, и вы можете поставить его, когда вы проверить свои объекты, а именно:

static readonly IConfigurationSource validationConfiguration = 
    new RoleConfigurationSource(); 

Validator customerValidator = 
    ValidationFactory.CreateValidator<Customer>(validationConfiguration); 

ValidationResults results = customerValidator.Validate(customer); 

if (!results.IsValid) 
{ 
    throw new InvalidOperationException(results[0].Message); 
} 

Пожалуйста, обратите внимание, что Validation Application Block не простой каркас. Это займет некоторое время, чтобы изучить его. Когда ваше приложение достаточно велико, ваши конкретные требования, однако, оправдают его использование.Если вы выберете VAB, начните с чтения документа «Hands-On Labs». Если у вас есть проблемы, вернитесь сюда в SO ;-)

Удачи.

+0

Подробнее об интеграции VAB с Entity Framework вы можете узнать здесь: http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=46 – Steven

+0

Спасибо за хорошую информацию. –

Смежные вопросы