2016-10-21 4 views
2

В настоящее время я пытаюсь создать собственное ограничение с помощью C# Entity Framework. Более подробно:C# Entity Framework Custom Constraint

У меня есть поле чисел, которое может иметь только определенные значения (например, 1, 2 и 3). Как достичь этого ограничения в первой среде кода?

+2

Что такое все теги Entity Framework? –

+0

Извините, удалили дубликаты –

ответ

2

Entity Framework автоматически проверяет любые валидации вы добавляете к вашей модели по ValidationAttribute с. RequiredAttribute или RangeAttribute - два примера встроенных подклассов этого атрибута.

Если вам нужна какая-то специальная проверка, наиболее удобным способом является контрейлерный переход на этот механизм и создание собственного подкласса ValidationAttribute.

Если вы хотите проверить не-непрерывный диапазон значений, которые вы не можете использовать RangeAttribute, но вы можете сделать свой собственный атрибут, например, так:

public class AllowedValuesAttribute : ValidationAttribute 
{ 
    private readonly ICollection<object> _validValues; 
    private readonly Type _type; 

    public AllowedValuesAttribute(Type type, object[] validValues) 
    { 
     _type = type; 
     _validValues = validValues.Where(v => v != null && v.GetType() == type).ToList(); 
    } 

    public override bool IsValid(object value) 
    { 
     return value.GetType() == _type && _validValues.Contains(value); 
    } 

    public override string FormatErrorMessage(string name) 
    { 
     return string.Format("Value for '{0}' is not an allowed value", name); 
    } 
} 

Использование:

[AllowedValues(typeof(int), new object[] { 1, 2, 4, 8, 16 })] 
public int Base { get; set; } 

Обратите внимание, что здесь мы должны использовать фиксированные значения, поскольку содержимое атрибута должно быть известно во время компиляции. Кроме того, мы должны использовать object, потому что (в настоящее время) C# не поддерживает общие атрибуты. Кроме того, существует множество вариантов. Например, атрибут может также иметь метод, который находит допустимые значения во время выполнения, возможно, из именованного источника, поэтому вы можете указать это имя в своем конструкторе.

Я не вижу никаких проблем в классах сущностей сущностей с атрибутами проверки. Модель сущности не модель домена, это часть уровня доступа к данным. Основной целью является (и должно быть) облегчение доступа к данным приложения. Если модель сущности также используется для поддержки бизнес-логики, это просто бонус.

+0

, подумав об этом, я до сих пор не знаю, почему s.o. будет использовать это. Атрибут для этого прост неправильным способом. Ваш пример показывает это: здесь это будет «Flag» -Enum или просто «Enum», если значения были, например. '1,3,7,20, ...'. Если данные имеют конкретное значение, вы должны создать таблицу и использовать PK как FK. Если вам действительно нужно использовать int (потому что, не знаю почему), вы будете обрабатывать его в контроллере или использовать аннотацию на viewmodel, поскольку другой контроллер, возможно, может ввести другой int - (if not, enum или FK it). Извините, но я до сих пор не вижу причин использовать его в классе сущностей. –

+0

@MatthiasBurger В приложении вы хотите иметь * единственную точку проверки *. Я бы никогда не использовал свойство setter, которое генерирует исключение. Это вводит много потенциальных мест кода, где должны обрабатываться исключения. И когда проверка EF срабатывает, свойство не проверяет. Преимущество атрибута заключается в том, что он проверяется в нужное время и в правильном направлении, то есть точно так же, как и другие проверки EF. Любые нарушения хорошо видны среди других ошибок проверки. Вы получаете много бесплатно. –

+0

@MatthiasBurger Конечно, я бы не использовал его для проверки FK и да, я бы рекомендовал перечисления. Атрибут может быть достаточно в относительно простых случаях. –

0

Очень плохая практика добавления данных в модель домена, например, D.Mac. А как насчет этого лучше?

public MyClass 
{  
    private int myNumberField; 
    public int MyNumberField 
    { 
     get { return myNumberField; } 
     set 
     { 
      if (value >= 1 && value <=3) 
       myNumberField = value; 
      else 
       // throw exception? 
       // set default-value (maybe 1)? 
       // do nothing? 
     } 
    } 

} 

вы могли бы сделать все, что вы хотите в инкубаторе вашей собственности

и только ограничивающем его в переднем конце не является лучшим решением, так как вы всегда можете изменить JavaScript/HTML - но вы должны покажите пользователю, что он может вставлять только значения 1, 2 или 3. Также ограничьте его в viewmodel аннотациями данных.

ИЛИ:

можно также переопределить EntityFrameworks SaveChanges и добавить BusinessLogic:

public override int SaveChanges(SaveOptions options) 
{ 

    foreach (ObjectStateEntry entry in 
     ObjectStateManager.GetObjectStateEntries(
     EntityState.Added | EntityState.Modified)) 
    { 
     // Validate the objects in the Added and Modified state 
     // if the validation fails, e.g. throw an exeption. 
    } 
    return base.SaveChanges(options); 
}