Свободные интерфейсы являются более гибкими, чем атрибуты и почему?

15

В руководстве EF 4.1 Code First указан следующий код:

public class Department
{
    public int DepartmentId { get; set; }
    [Required]
    public string Name { get; set; }
    public virtual ICollection<Collaborator> Collaborators { get; set; }
}

Затем объясняется, что свободный интерфейс более гибок:

Аннотации данных, безусловно, просты в использовании, но предпочтительно использовать программный подход, который обеспечивает гораздо большую гибкость.

Далее приведен пример использования свободного интерфейса:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Department>().Property(dp => dp.Name).IsRequired();
    modelBuilder.Entity<Manager>().HasKey(ma => ma.ManagerCode);
    modelBuilder.Entity<Manager>().Property(ma => ma.Name)
        .IsConcurrencyToken(true)
        .IsVariableLength()
        .HasMaxLength(20);
}

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

Мой вопрос: почему свободный интерфейс будет лучшим вариантом, чем использование атрибутов, особенно в этом случае?

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

Ссылка: http://codefirst.codeplex.com/

Tjaart
источник
Этот вопрос не совсем о беглых интерфейсах. Разница между использованием атрибутов и нормального кода. Если бы код не был свободным, это не сильно изменило бы ваш вопрос.
svick
Свободные интерфейсы @svick - это обычный код, но он выражает его по-другому. Мы отошли от указания вещей в простом коде к атрибутам, теперь с плавными интерфейсами кажется, что некоторые возвращаются назад и снова переходят к определению вещей в коде. Я просто хочу понять, почему вы используете код вместо атрибутов. Свободные интерфейсы гарантируют переход от атрибутов и обратно к простому повторному кодированию?
Tjaart

Ответы:

13

Аннотации данных являются статическими, например, это объявление метода не может измениться во время выполнения:

  [MinLength(5)]
  [MaxLength(20,ErrorMessage="Le nom ne peut pas avoir plus de 20 caractères")]
  public new string Name { get; set; }

Свободный интерфейс может быть динамическим:

   if (longNamesEnabled)
   {
      modelBuilder.Entity<Manager>().Property(ma => ma.Name)
        .HasMaxLength(100);
   }
   else
   {
      modelBuilder.Entity<Manager>().Property(ma => ma.Name)
        .HasMaxLength(20);
   }

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

Гарретт Холл
источник
2
почему вы думаете, что длина (или любое другое свойство) того же свойства изменится во время выполнения?
Юсубов
1
@ElYusubov: я бы начал со сценариев, когда я не знал длины поля во время кодирования.
Уайетт Барнетт
@WyattBarnett: может иметь смысл иметь длину поля в качестве переменной, только когда параметры домена динамически выбираются из некоторого сервиса или внешнего нетипизированного источника. Однако динамическое обращение со свойствами домена потребует подхода защитного кодирования.
Юсубов
1
@ElYusubov у вас может быть два свойства, которые должны быть одинаковыми, за исключением длины, поэтому я передаю их в функцию, которая устанавливает их динамически. Вот почему автор назвал их более гибкими.
Гаррет Холл
1
@ElYusubov, вы можете сделать длину поля настройкой в ​​настройках проекта, которая подается в app.config или web.config. Затем, если длина поля базы данных изменилась, вы можете изменить длину в файле .config без перекомпиляции и повторного развертывания приложения.
Kyralessa
8

Я не думаю, что это заявление должно широко применяться; это очень специфично для Code First. В Code First аннотации данных включают только подмножество функций, доступных в свободном API. Другими словами, существуют определенные конфигурации моделей, которые могут быть выполнены только с использованием свободно распространяемого API.

Например, вот некоторые вещи, которые нельзя указать с помощью аннотаций:

  • Точность свойства DateTime
  • Точность и масштаб числовых свойств
  • Строковое или двоичное свойство как фиксированной длины
  • Свойство String как не-Unicode
  • Поведение при удалении отношений
  • Продвинутые картографические стратегии

Лично я стараюсь использовать аннотации данных, связанные с проверкой, когда это возможно, поскольку другие технологии, такие как MVC, также могут использовать их. Для всего остального я предпочитаю свободный API.

bricelam
источник
Можете ли вы привести пример того, что можно сделать только с помощью свободного API? Также было бы интересно узнать, почему они решили сделать это таким образом. Я пытаюсь понять неоправданные API по сравнению с более традиционными методами, а структура сущностей - только пример. Я хочу знать, почему они предпочли бы это атрибутам. Мне атрибуты кажутся более правильными и читаемыми.
Tjaart
1
@Tjaart Я добавил несколько примеров. При разработке этого было два основных мотивационных принципа. Во-первых, позвольте разработчикам выбирать. Некоторые люди рассматривают атрибуты как нарушение POCO, другим нравится их декларативный характер. Во-вторых, использовать существующие атрибуты и вводить новые только для общих сценариев. Вы, вероятно, согласитесь, что примеры, которые я привел выше, относительно редки.
bricelam
Я заметил, что поведение OnDelete доступно только в свободном API. Можете ли вы подумать, почему они решили сделать это таким образом? Это действительно то, что я пытаюсь решить с этим вопросом. Нарушение POCO может быть хорошей причиной, если вы разделяете занятия между проектами. Вы можете в конечном итоге получить зависимость структуры сущностей, которая вам не нужна, если вы используете атрибуты!
Tjaart
@ Тьяарт, я не помню точных причин. Я присоединился к команде ближе к концу функции Code First и не был здесь из-за ее дизайна. Я посмотрю, смогу ли я получить кого-то еще из команды, чтобы взвесить, хотя.
bricelam
1

Ответ на ваш вопрос приведен в ссылке.

Затем вы определяете свои ограничения, применимые к вашему домену в рамках этого метода программно.

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

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

Однако для распространенных сценариев проверки применение атрибутов должно работать нормально, поскольку оно надежно для большинства случаев; и кроме того, это может сэкономить ваше время.

Юсубы
источник
Можете ли вы показать, как программный способ дает вам больше контроля? Я на самом деле не понимаю этого.
Tjaart
Например, возьмите этот «.IsConcurrencyToken (true)» - как бы вы сделали это в определении атрибута?
Юсубов
[ConcurrencyCheck] <- что на самом деле кажется проще
Tjaart
хороший улов, как бы вы описали «отношения между таблицами и столбцами»?
Юсубов
[ForeignKey ("PersonId")] <- вроде бы так, что, вероятно, не так просто, как .HasForeignKey (t => t.ProjectId), хотя все, что нужно, это позволить ForeignKey () взять лямбду, точно так же, как свободный интерфейс. Это все еще не объясняет, почему один лучше, чем другой.
Tjaart
0

Я думаю, что они рекомендуют свободный API для первых реализаций кода, потому что вы явно описываете, как создаются отношения в базе данных. Если вы используете аннотации данных, база данных, созданная Entity Framework, может не соответствовать вашим ожиданиям. Ваш первоначальный пример очень прост, поэтому, как и вы, я бы просто использовал метод аннотации данных.

str8killinit
источник
Можете ли вы привести пример того, что база данных не соответствует вашим ожиданиям и как свободный интерфейс предотвращает это?
Tjaart