Les interfaces fluides sont-elles plus flexibles que les attributs et pourquoi?

15

Dans un didacticiel EF 4.1 Code First, le code suivant est fourni:

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

Ensuite, il est expliqué que l'interface fluide est plus flexible:

Les annotations de données sont certainement faciles à utiliser, mais il est préférable d'utiliser une approche programmatique qui offre beaucoup plus de flexibilité.

L'exemple d'utilisation de l'interface fluide est alors donné:

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);
}

Je ne comprends pas pourquoi l'interface fluide est censée être meilleure. Est ce que c'est vraiment? De mon point de vue, il semble que les annotations de données soient plus claires et plus sémantiques.

Ma question est pourquoi une interface fluide serait-elle une meilleure option que l'utilisation d'attributs, en particulier dans ce cas?

(Remarque: je suis assez nouveau dans le concept d'interfaces fluides, alors ne vous attendez à aucune connaissance préalable à ce sujet.)

Référence: http://codefirst.codeplex.com/

Tjaart
la source
Cette question ne concerne pas vraiment les interfaces fluides. La différence est entre l'utilisation d'attributs et le code normal. Si le code n'était pas fluide, cela ne changerait pas grand-chose à votre question.
svick
Les interfaces fluides @svick sont essentiellement du code normal, mais il l'exprime d'une manière différente. Nous nous sommes éloignés de la spécification de choses en code clair en attributs, maintenant avec des interfaces fluides, il semble que certains reviennent en arrière et se dirigent vers la spécification de choses en code à nouveau. Je veux juste comprendre pourquoi vous utiliseriez du code au lieu d'attributs. Les interfaces fluides justifient-elles de s'éloigner des attributs pour revenir à tout simplement coder à nouveau?
Tjaart

Réponses:

13

Les annotations de données sont statiques, par exemple, cette déclaration de méthode ne peut pas changer au moment de l'exécution:

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

L'interface fluide peut être dynamique:

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

sans oublier que le code peut être réutilisé entre les propriétés.

Garrett Hall
la source
2
pourquoi pensez-vous que la longueur (ou toute autre propriété) de la même propriété changerait au moment de l'exécution?
Yusubov
1
@ElYusubov: Je commencerais par les scénarios où je ne connaissais pas la longueur du champ au moment du codage.
Wyatt Barnett
@WyattBarnett: il peut être judicieux d'avoir la longueur de champ en tant que variable uniquement lorsque les paramètres de domaine sont extraits dynamiquement à partir d'un service ou d'une source externe non typée. Cependant, le traitement dynamique des propriétés de domaine nécessiterait une approche de codage défensive.
Yusubov
1
@ElYusubov, vous pourriez avoir deux propriétés qui doivent être exactement les mêmes, sauf pour la longueur, je les passe donc dans une fonction qui les configure dynamiquement. C'est pourquoi l'auteur les a appelés plus flexibles.
Garrett Hall
1
@ElYusubov, vous pouvez définir la longueur du champ comme un paramètre dans les paramètres du projet, qui alimente app.config ou web.config. Ensuite, si la longueur d'un champ de base de données a changé, vous pouvez modifier la longueur dans le fichier .config sans recompiler et redéployer l'application.
Kyralessa
8

Je ne pense pas que cette déclaration devrait être largement appliquée; il est très spécifique à Code First. Dans Code First, les annotations de données incluent uniquement un sous-ensemble des fonctionnalités disponibles dans l'API fluide. En d'autres termes, certaines configurations de modèle ne peuvent être effectuées qu'à l'aide de l'API courante.

Par exemple, voici certaines choses qui ne peuvent pas être spécifiées à l'aide des annotations:

  • La précision d'une propriété DateTime
  • La précision et l'échelle des propriétés numériques
  • Une propriété String ou Binary de longueur fixe
  • Une propriété String non-unicode
  • Le comportement à la suppression des relations
  • Stratégies de cartographie avancées

Personnellement, j'ai tendance à utiliser les annotations de données liées à la validation chaque fois que possible, car d'autres technologies comme MVC peuvent également en profiter. Pour tout le reste, je préfère l'API couramment.

bricelam
la source
Pouvez-vous donner un exemple de ce qui ne peut être fait qu'en utilisant l'API fluide? Il serait également intéressant de savoir pourquoi ils ont choisi de procéder de cette façon. Im essayant de comprendre les API fleunt par rapport aux méthodes plus conventionnelles et au cadre d'entité n'est qu'un exemple. Je veux savoir pourquoi ils le préfèrent aux attributs. Les attributs me semblent plus corrects et lisibles.
Tjaart
1
@Tjaart J'ai ajouté quelques exemples. Lors de sa conception, il y avait deux principes de motivation principaux. Tout d'abord, laissez les développeurs choisir. Certaines personnes considèrent les attributs comme une violation de POCO, d'autres comme leur nature déclarative. Deuxièmement, exploitez les attributs existants et n'en introduisez de nouveaux que pour les scénarios courants. Vous conviendrez probablement que les exemples que j'ai donnés ci-dessus sont relativement rares.
bricelam
J'ai remarqué que le comportement OnDelete ne semble être disponible que dans l'API fluide. Pouvez-vous imaginer pourquoi ils ont choisi de le faire de cette façon? C'est vraiment ce que j'essaie de comprendre avec cette question. La violation de POCO peut être une bonne raison si vous partagez les classes entre projets. Vous pouvez finir par extraire une dépendance de structure d'entité dont vous ne voulez pas si vous utilisez des attributs!
Tjaart
@Tjaart, je ne me souviens pas des raisons exactes. J'ai rejoint l'équipe vers la fin de la fonctionnalité Code First et je n'étais pas là pour sa conception. Je vais voir si je peux demander à quelqu'un d'autre de l'équipe de peser.
bricelam
1

La réponse à votre question est fournie dans le lien.

Ensuite, vous définissez vos contraintes applicables à votre domaine dans cette méthode par programme.

Fondamentalement, il est plus ou moins préférable d'utiliser Attributs vs approche programmatique, où l'approche programmatique a plus de contrôle sur l'entité. Cependant, il existe un moyen personnalisé d'ajouter des attributs pour décorer votre modèle que vous pouvez également regarder.

Lorsque vous utilisez cette approche, vous pouvez même décrire les relations entre les tables et les colonnes. En fin de compte, si vous souhaitez avoir un contrôle plus précis sur votre domaine, vous pouvez utiliser cette nouvelle approche fournie avec EF4.1.

Cependant, pour les scénarios courants de validation, l' application des attributs devrait fonctionner correctement car elle est robuste pour couvrir la plupart des cas; et en plus cela pourrait vous faire gagner du temps.

Yusubov
la source
Pouvez-vous illustrer comment la manière programmatique vous donne plus de contrôle? Je ne comprends pas vraiment à ce stade.
Tjaart
Par exemple, prenez ce ".IsConcurrencyToken (true)" - comment vous procéderiez sur une définition d'attribut?
Yusubov
[ConcurrencyCheck] <- ce qui semble en fait plus simple
Tjaart
bonne prise, comment décririez-vous alors "les relations entre les tables et les colonnes"?
Yusubov
[ForeignKey ("PersonId")] <- comme cela, ce qui n'est probablement pas aussi simple que .HasForeignKey (t => t.ProjectId), bien que tout ce qui soit nécessaire soit de laisser ForeignKey () prendre un lambda tout comme l'interface fluide. Cela n'explique toujours pas pourquoi l'un est meilleur que l'autre.
Tjaart
0

Je pense qu'ils recommandent l'API courante pour les premières implémentations de code parce que vous décrivez explicitement comment les relations sont créées dans la base de données. Si vous utilisez des annotations de données, la base de données créée par Entity Framework peut ne pas être celle que vous attendez. Votre exemple initial est très simple, donc, comme vous, j'utiliserais simplement la méthode d'annotation des données.

str8killinit
la source
Pouvez-vous donner un exemple de la base de données qui ne correspond pas à vos attentes et comment une interface fluide empêche cela de se produire?
Tjaart