Sind fließende Schnittstellen flexibler als Attribute und warum?

15

In einem EF 4.1 Code First Tutorial wird der folgende Code angegeben:

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

Dann wird erklärt, dass das flüssige Interface flexibler ist:

Datenanmerkungen sind auf jeden Fall einfach zu verwenden, es ist jedoch vorzuziehen, einen programmgesteuerten Ansatz zu verwenden, der viel mehr Flexibilität bietet.

Das Beispiel für die Verwendung der flüssigen Schnittstelle wird dann gegeben:

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

Ich kann nicht verstehen, warum das fließende Interface angeblich besser ist. Ist das wirklich? Aus meiner Sicht sieht es so aus, als wären die Datenanmerkungen klarer und hätten ein klareres semantisches Gefühl.

Meine Frage ist, warum eine flüssige Benutzeroberfläche eine bessere Option ist als die Verwendung von Attributen, insbesondere in diesem Fall.

(Hinweis: Ich bin ziemlich neu im Bereich der fließenden Benutzeroberflächen. Erwarten Sie daher bitte keine Vorkenntnisse.)

Referenz: http://codefirst.codeplex.com/

Tjaart
quelle
Bei dieser Frage geht es nicht wirklich um fließende Schnittstellen. Der Unterschied besteht zwischen der Verwendung von Attributen und normalem Code. Wenn der Code nicht fließend wäre, würde sich an Ihrer Frage nicht viel ändern.
Svick
@svick Fluent Interfaces sind im Prinzip normaler Code, der sich jedoch anders ausdrückt. Wir haben uns von der Angabe von Dingen in einfachem Code zu Attributen abgewandt. Bei fließenden Benutzeroberflächen sieht es so aus, als würden sich einige zurückverfolgen und darauf hinarbeiten, Dinge wieder in Code anzugeben. Ich möchte nur verstehen, warum Sie Code anstelle von Attributen verwenden würden. Müssen fließende Schnittstellen von Attributen weg und zurück, um alles einfach wieder zu codieren?
Tjaart

Antworten:

13

Datenanmerkungen sind statisch. Diese Methodendeklaration kann beispielsweise zur Laufzeit nicht geändert werden:

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

Das flüssige Interface kann dynamisch sein:

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

Ganz zu schweigen davon, dass der Code zwischen Eigenschaften wiederverwendet werden kann.

Garrett Hall
quelle
2
Warum sollte sich die Länge (oder eine andere Eigenschaft) derselben Eigenschaft in der Laufzeit ändern?
Yusubov
1
@ElYusubov: Ich würde mit den Szenarien beginnen, in denen ich die Feldlänge zum Codierungszeitpunkt nicht kannte.
Wyatt Barnett
@WyattBarnett: Es kann sinnvoll sein, die Feldlänge nur dann als Variable anzugeben, wenn Domänenparameter dynamisch von einem Dienst oder einer externen nicht typisierten Quelle abgerufen werden. Ein dynamischer Umgang mit Domäneneigenschaften würde jedoch einen defensiven Codierungsansatz erfordern.
Yusubov
1
@ElYusubov Sie könnten zwei Eigenschaften haben, die bis auf die Länge genau gleich sein müssen, damit ich sie in eine Funktion übergebe, die sie dynamisch einrichtet. Deshalb nannte der Autor sie flexibler.
Garrett Hall
1
@ElYusubov, Sie können die Feldlänge in den Projekteinstellungen festlegen, die in die Datei app.config oder web.config eingehen. Wenn sich dann die Länge eines Datenbankfelds ändert, können Sie die Länge in der .config-Datei ändern, ohne die App neu kompilieren und erneut bereitstellen zu müssen.
Kyralessa
8

Ich denke nicht, dass diese Aussage allgemein angewendet werden sollte; es ist sehr spezifisch für Code First. In Code First enthalten Datenanmerkungen nur eine Teilmenge der Funktionen, die in der Fluent-API verfügbar sind. Mit anderen Worten, es gibt bestimmte Modellkonfigurationen, die nur mit der flüssigen API durchgeführt werden können.

Zum Beispiel sind hier einige der Dinge, die mit den Annotationen nicht angegeben werden können:

  • Die Genauigkeit einer DateTime-Eigenschaft
  • Die Genauigkeit und Skalierung von numerischen Eigenschaften
  • Eine Zeichenfolge oder Binäreigenschaft mit fester Länge
  • Eine String-Eigenschaft als Nicht-Unicode
  • Das Verhalten beim Löschen von Beziehungen
  • Erweiterte Mapping-Strategien

Persönlich verwende ich die validierungsbezogenen Datenkommentare, wann immer dies möglich ist, da auch andere Technologien wie MVC diese nutzen können. Für alles andere bevorzuge ich die flüssige API.

Bricelam
quelle
Können Sie ein Beispiel dafür geben, was nur mit der flüssigen API möglich ist? Es wäre auch interessant zu wissen, warum sie sich dafür entschieden haben, es auf diese Weise zu tun. Ich versuche zu verstehen, fleunt APIs im Vergleich zu konventionellen Methoden und Entity Framework ist nur ein Beispiel. Ich möchte wissen, warum sie es den Attributen vorziehen würden. Attribute erscheinen mir korrekter und lesbarer.
Tjaart
1
@Tjaart Ich habe einige Beispiele hinzugefügt. Bei der Gestaltung wurden zwei Hauptmotivationsprinzipien berücksichtigt. Lassen Sie zunächst die Entwickler auswählen. Manche Menschen sehen Attribute als Verstoß gegen POCO an, andere mögen ihre deklarative Natur. Zweitens, nutzen Sie vorhandene Attribute und führen Sie nur neue für gängige Szenarien ein. Sie werden wahrscheinlich zustimmen, dass die Beispiele, die ich oben gegeben habe, relativ selten sind.
Bricelam
Mir ist aufgefallen, dass das Verhalten von OnDelete nur in der flüssigen API verfügbar zu sein scheint. Kannst du dir vorstellen, warum sie es so gemacht haben? Das ist wirklich das, worauf ich mit dieser Frage hinaus will. Die POCO-Verletzung kann ein guter Grund sein, wenn Sie die Klassen zwischen Projekten teilen. Es kann vorkommen, dass Sie eine Entity-Framework-Abhängigkeit abrufen, die Sie nicht benötigen, wenn Sie Attribute verwenden!
Tjaart
@Tjaart, ich erinnere mich nicht an die genauen Gründe. Ich bin gegen Ende des Code First-Features dem Team beigetreten und war nicht wegen des Designs hier. Ich werde sehen, ob ich jemand anderen aus dem Team dazu bringen kann, sich einzumischen.
Bricelam
1

Die Antwort auf Ihre Frage finden Sie im Link.

Anschließend definieren Sie programmgesteuert die Einschränkungen, die für Ihre Domain gelten.

Grundsätzlich ist es mehr oder weniger bevorzugt, Attribute im Vergleich zum programmatischen Ansatz zu verwenden, bei dem der programmatische Ansatz mehr Kontrolle über die Entität hat. Es gibt jedoch eine benutzerdefinierte Methode zum Hinzufügen von Attributen, um Ihr Modell so zu dekorieren, dass Sie auch aussehen können.

Mit diesem Ansatz können Sie sogar Beziehungen zwischen Tabellen und Spalten beschreiben. Fazit: Wenn Sie eine genauere Kontrolle über Ihre Domain wünschen, können Sie diesen neuen Ansatz von EF4.1 verwenden.

Doch für allgemeine Szenarien der Validierung Anwendung Attribute sollten funktionieren , weil es robust ist die meisten Fälle zu decken; Außerdem können Sie Zeit sparen.

Yusubov
quelle
Können Sie veranschaulichen, wie der programmatische Weg Ihnen mehr Kontrolle gibt? Ich verstehe es zum jetzigen Zeitpunkt nicht wirklich.
Tjaart
Nehmen Sie zum Beispiel ".IsConcurrencyToken (true)" - wie würden Sie dies für eine Attributdefinition tun?
Yusubov
[ConcurrencyCheck] <- was eigentlich einfacher erscheint
Tjaart
guter Fang, wie würden Sie dann "Relationen zwischen Tabellen und Spalten" beschreiben?
Yusubov
[ForeignKey ("PersonId")] <- wie so, was wahrscheinlich nicht so einfach ist wie .HasForeignKey (t => t.ProjectId), obwohl alles, was benötigt wird, ist, ForeignKey () ein Lambda nehmen zu lassen, genau wie die fließende Schnittstelle. Es erklärt immer noch nicht, warum einer besser ist als der andere.
Tjaart
0

Meiner Meinung nach empfehlen sie die fließende API für Code-First-Implementierungen, da Sie explizit beschreiben, wie die Beziehungen in der Datenbank erstellt werden. Wenn Sie Datenanmerkungen verwenden, entspricht die von Entity Framework erstellte Datenbank möglicherweise nicht Ihren Erwartungen. Ihr erstes Beispiel ist sehr einfach, daher würde ich wie Sie nur die Datenanmerkungsmethode verwenden.

str8killinit
quelle
Können Sie ein Beispiel dafür geben, dass die Datenbank nicht Ihren Erwartungen entspricht und wie eine flüssige Schnittstelle dies verhindert?
Tjaart