webentwicklung-frage-antwort-db.com.de

Wie sollte ich Fremdschlüsselbeziehungen mit Code First Entity Framework (4.1) in MVC3 deklarieren?

Ich habe nach Ressourcen gesucht, wie Fremdschlüsselbeziehungen und andere Einschränkungen mit Code EF 4.1 deklariert werden können, ohne viel Glück zu haben. Grundsätzlich baue ich das Datenmodell in Code und verwende MVC3, um dieses Modell abzufragen. Alles funktioniert über MVC, was großartig ist (ein großes Lob an Microsoft!), Aber jetzt möchte ich, dass es NICHT funktioniert, weil ich Einschränkungen für das Datenmodell haben muss.

Ich habe zum Beispiel ein Order-Objekt mit einer Vielzahl von Eigenschaften, die externe Objekte (Tabellen) sind. Im Moment kann ich problemlos einen Auftrag erstellen, ohne jedoch den Fremdschlüssel oder externe Objekte hinzufügen zu können. MVC3 stellt dies kein Problem dar.

Ich erkenne, dass ich die Objekte vor dem Speichern einfach selbst in der Controller-Klasse hinzufügen könnte, aber ich möchte, dass der Aufruf von DbContext.SaveChanges () fehlschlägt, wenn die Abhängigkeiten nicht erfüllt sind.

NEUE INFORMATIONEN

Daher möchte ich, dass eine Ausnahme auftritt, wenn ich versuche, ein Bestellobjekt zu speichern, ohne ein Kundenobjekt anzugeben. Dies scheint nicht das Verhalten zu sein, wenn ich die Objekte nur wie in den meisten Code First EF-Dokumentationen beschrieben zusammensetze.

Letzter Code:

public class Order
{
    public int Id { get; set; }

    [ForeignKey( "Parent" )]
    public Patient Patient { get; set; }

    [ForeignKey("CertificationPeriod")]
    public CertificationPeriod CertificationPeriod { get; set; }

    [ForeignKey("Agency")]
    public Agency Agency { get; set; }

    [ForeignKey("Diagnosis")]
    public Diagnosis PrimaryDiagnosis { get; set; }

    [ForeignKey("OrderApprovalStatus")]
    public OrderApprovalStatus ApprovalStatus { get; set; }

    [ForeignKey("User")]
    public User User { get; set; }

    [ForeignKey("User")]
    public User Submitter { get; set; }

    public DateTime ApprovalDate { get; set; }
    public DateTime SubmittedDate { get; set; }
    public Boolean IsDeprecated { get; set; }
}

Dies ist der Fehler, den ich jetzt bekomme, wenn ich auf die VS-generierte Ansicht für den Patienten zugreife:

FEHLERMELDUNG

Das ForeignKeyAttribute für die Eigenschaft 'Patient' vom Typ 'PhysicianPortal.Models.Order' ist ungültig. Der Fremdschlüsselname 'Parent' wurde im abhängigen Typ 'PhysicianPortal.Models.Order' nicht gefunden. Der Wert Name sollte eine durch Kommas getrennte Liste von Fremdschlüsseleigenschaftsnamen sein.

Grüße,

Guido

95
Guido Anselmi

Wenn Sie eine Order -Klasse haben, sollte das Hinzufügen einer Eigenschaft, die auf eine andere Klasse in Ihrem Modell verweist, beispielsweise Customer ausreichen, um EF mitzuteilen, dass dort eine Beziehung besteht:

public class Order
{
    public int ID { get; set; }

    // Some other properties

    // Foreign key to customer
    public virtual Customer Customer { get; set; }
}

Sie können die FK -Relation jederzeit explizit festlegen:

public class Order
{
    public int ID { get; set; }

    // Some other properties

    // Foreign key to customer
    [ForeignKey("Customer")]
    public string CustomerID { get; set; }
    public virtual Customer Customer { get; set; }
}

Der Konstruktor ForeignKeyAttribute akzeptiert einen String als Parameter: Wenn Sie ihn auf einer Fremdschlüsseleigenschaft platzieren, repräsentiert er den Namen der zugeordneten Navigationseigenschaft. Wenn Sie es auf der Navigationseigenschaft platzieren, wird der Name des zugeordneten Fremdschlüssels angezeigt.

Wenn Sie das ForeignKeyAttribute in der Customer -Eigenschaft platzieren, würde das Attribut CustomerID im Konstruktor annehmen:

public string CustomerID { get; set; }
[ForeignKey("CustomerID")]
public virtual Customer Customer { get; set; }

BEARBEITEN basierend auf Neuestem Code Sie erhalten diesen Fehler aufgrund der folgenden Zeile:

[ForeignKey("Parent")]
public Patient Patient { get; set; }

EF sucht nach einer Eigenschaft namens Parent, um sie als Foreign Key Enforcer zu verwenden. Sie können zwei Dinge tun:

1) Entfernen Sie das ForeignKeyAttribute und ersetzen Sie es durch das RequiredAttribute, um die Beziehung wie erforderlich zu markieren:

[Required]
public virtual Patient Patient { get; set; }

Das Dekorieren einer Eigenschaft mit dem RequiredAttribute hat auch einen netten Nebeneffekt: Die Relation in der Datenbank wird mit ON DELETE CASCADE Erstellt.

Ich würde auch empfehlen, die Eigenschaft virtual zu erstellen, um Lazy Loading zu aktivieren.

2) Erstellen Sie eine Eigenschaft mit dem Namen Parent, die als Fremdschlüssel dient. In diesem Fall ist es wahrscheinlich sinnvoller, es zum Beispiel ParentID aufzurufen (Sie müssen den Namen auch in ForeignKeyAttribute ändern):

public int ParentID { get; set; }

Meiner Erfahrung nach funktioniert es in diesem Fall jedoch besser, es anders herum zu haben:

[ForeignKey("Patient")]
public int ParentID { get; set; }

public virtual Patient Patient { get; set; }
154
Sergi Papaseit

Sie können Fremdschlüssel folgendermaßen definieren:

public class Parent
{
   public int Id { get; set; }
   public virtual ICollection<Child> Childs { get; set; }
}

public class Child
{
   public int Id { get; set; }
   // This will be recognized as FK by NavigationPropertyNameForeignKeyDiscoveryConvention
   public int ParentId { get; set; } 
   public virtual Parent Parent { get; set; }
}

Jetzt ist ParentId eine Fremdschlüsseleigenschaft und definiert die erforderliche Beziehung zwischen dem untergeordneten und dem vorhandenen übergeordneten Element. Wenn Sie das Kind speichern, ohne das Elternteil zu verlassen, wird eine Ausnahme ausgelöst.

Wenn der Name Ihrer FK-Eigenschaft nicht aus dem Namen der Navigationseigenschaft und dem Namen der übergeordneten PK besteht, müssen Sie entweder die Datenanmerkung ForeignKeyAttribute oder die API fluent verwenden, um die Beziehung abzubilden

Datenanmerkung:

// The name of related navigation property
[ForeignKey("Parent")]
public int ParentId { get; set; }

Fließende API:

modelBuilder.Entity<Child>()
            .HasRequired(c => c.Parent)
            .WithMany(p => p.Childs)
            .HasForeignKey(c => c.ParentId);

Andere Arten von Einschränkungen können durch Datenanmerkungen und Modellvalidierung erzwungen werden.

Bearbeiten:

Sie erhalten eine Ausnahme, wenn Sie ParentId nicht festlegen. Es ist eine erforderliche Eigenschaft (nicht nullwertfähig). Wenn Sie dies nicht tun, wird höchstwahrscheinlich versucht, einen Standardwert an die Datenbank zu senden. Der Standardwert ist 0. Wenn Sie also keinen Kunden mit der ID 0 haben, wird eine Ausnahme ausgelöst.

29
Ladislav Mrnka