Frage

Wie ein Eins-zu Eins-Beziehung zu erklären, mit Entity Framework 4 Code First (POCO)?

Ich fand diese Frage (ein- zu-eins-Beziehungen in Entity Framework 4) , aber der Artikel, dass die Antwort Referenzen nicht nützlich waren (es gibt eine Codezeile, die eine 1-1-Beziehung ist, aber nicht erwähnt, wie es zu definieren).

War es hilfreich?

Lösung

Suchen Sie einfach nach so etwas wie das?

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public Profile Profile { get; set; }
    public int ProfileId { get; set; }
}

public class Profile
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PostalCode { get; set; }
    // etc...
}

public class UserMapping : EntityConfiguration<User>
{
    public UserMapping()
    {
        this.HasKey(u => u.Id);
        this.Property(u => u.Username).HasMaxLength(32);

        // User has ONE profile.
        this.HasRequired(u => u.Profile);
    }
}

public class ProfileMapping : EntityConfiguration<Profile>
{
    public ProfileMapping()
    {
        this.HasKey(p => p.Id);
        this.Property(p => p.FirstName).HasMaxLength(32);
        this.Property(p => p.LastName).HasMaxLength(32);
        this.Property(p => p.PostalCode).HasMaxLength(6);
    }
}

Bearbeiten : Ja, ich habe VS nicht vor mir, aber Sie müssen die folgende Zeile in den UserMapping anstelle dem aktuellen HasRequired hinzufügen und auch eine ProfileId Eigenschaft hinzufügen (statt Profile_Id dass Sie ergänzt):

this.HasRequired(u => u.Profile).HasConstraint((u, p) => u.ProfileId == p.Id);

Ich glaube, zur Zeit nicht gibt es einen Weg, um dieses, aber ich bin sicher, es wird sich ändern, da wir nur in CTP4 sind. Es wäre schön, wenn ich sagen könnte:

this.HasRequired(u => u.Profile).WithSingle().Map(
    new StoreForeignKeyName("ProfileId"));

Auf diese Weise würde ich nicht eine ProfileId Unterkunft zählen müssen. Vielleicht gibt es eine Möglichkeit, um diese zur Zeit und es ist noch zu früh am Morgen für mich zu denken.)

Denken Sie auch daran .Include("Profile") zu nennen, wenn Sie eine „Navigations-Eigenschaft“ enthalten sein sollen.

Andere Tipps

Drei Methoden:

A) erklärt beiden Klassen mit Navigationseigenschaften zueinander. Markieren Sie eine der Tabellen (die abhängige Tabelle) mit dem ForeignKey Attribute auf seinem Primärschlüssel. EF folgert 1-zu-1 aus folgt aus:

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

    public string Username { get; set; }

    public OpenIdInfo OpenIdInfo { get; set; }
}

​public class OpenIdInfo
{
    [ForeignKey("AppUser")]
    public int Id { get; set; }

    public string OpenId { get; set; }

    public AppUser AppUser { get; set; }
}

http://weblogs.asp.net/manavi/archive/2011/05/01/associations-in-ef-4-1-code-first- Teil-5-one-to-one-Fremdschlüssel-associations.aspx

Ich habe nicht virtual verwenden und Sie sollten auch nicht. *

B) Deklarieren Sie eine Vererbungshierarchie mit beiden Tabellennamen explizit angegeben, was in Tabelle pro Typ und einem gemeinsam genutzten Primärschlüssel.

using System.ComponentModel.DataAnnotations;

[Table("AppUser")]
public class AppUser
{
    public int Id { get; set; }

    public string Username { get; set; }

    public OpenIdInfo OpenIdInfo { get; set; }
}

[Table("AdminUser")]      
public class AdminUser : AppUser
{
    public bool SuperAdmin { get; set; }
}

Sie werden 2 Tabellen erhalten: Eine für AppUser, eine für Adminuser. Adminuser ist 1: 1 mit AppUser und ist abhängig - das heißt, Sie eine Adminuser löschen können, aber wenn Sie eine AppUser löschen, wenn ein Adminuser noch auf das Gerät gerichtet ist, werden Sie eine Beschränkungsverletzung Fehler.

C) Es gibt 2 auf halben Weg Methoden zu tun, eine Eins-zu-eins in EF:

Entity-Splitting , in dem Sie eine einzelne Klasse haben, aber es ist in einer primären Tabelle gespeichert, und 1 oder mehr eins-zu-eins-verknüpften Tabellen.

Table-Splitting , wo ein Baum von Objekten flacht zu einem einzigen Tisch. Zum Beispiel einer Klasse mit einer Eigenschaft Adresse würde Spalten für das Adressobjekt hat, wie ADDRESS_CITY, in eine einzige Tabelle abgeflacht.

* können Sie virtuelle gehören auf jeden EF oder der Kollektionen , wenn Sie zu faul Last wollen sie . Dies kann in Endlosschleifen führen oder die gesamte DB Laden, wenn Sie ein Objekt mit faul belasteten Eigenschaften, zum Beispiel des MVC JSON-Wandler oder irgendetwas anderes übergeben, die die Objekthierarchie geht. Das Lazy-Loading ist immer synchron erfolgt, den Faden zu blockieren, und ohne Vorankündigung. Um es zusammenzufassen, um die Liste der Möglichkeiten, wie Sie Ihren Code, App oder Server einfrieren kann es lang ist. Vermeiden Sie virtuelle Verwendung auf EF-Klassen. Ja, es gibt eine Menge von Code-Beispielen im Internet, die es verwenden. Nein, Sie sollten noch nicht verwenden.

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }

    public virtual Profile Profile { get; set; }
}

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

    public int UserID { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PostalCode { get; set; }
}

Fügen Sie das virtuelle Profil und die Benutzer-ID und ich denke, dass sollten Sie dort ankommen.

Nehmen wir ein Beispiel aus den folgenden Studenten und StudentAddress Einheiten.
Konfigurieren einer Eins-zu-Null-oder-eins-Beziehung DataAnnotations mit:

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    [ForeignKey("Student")]
    public int StudentAddressId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

Wenn StudentAddress Einheit Konventionen nicht folgt:

Wenn zum Beispiel nicht StudentAddress Unternehmen folgen nicht der Konvention für PK das heißt unterschiedliche Namen für Id-Eigenschaft dann müssen Sie auch für PK konfigurieren. Betrachten Sie die folgende StudentAddress Einheit, die hat Eigenschaftsnamen StudentID statt StudentAddressId.

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    [Key, ForeignKey("Student")]
    public int StudentId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

Im obigen Beispiel müssen wir configure StudentID Eigenschaft als Key sowie ForeignKey. Dadurch wird StudentID Eigenschaft in StudentAddress Einheit als PK und FK beide.

Konfigurieren One-to-Zero-oder-eins-Beziehung mit Fluent API:
Wenn Schüler und StudentAddress folgen den Konventionen: Student und StudentAddress Einheiten folgen Sie den Standardcode-first-Konvention für PrimaryKey. So haben wir nicht brauchen, um sie zu konfigurieren, um ihre PrimaryKeys zu definieren. Wir brauchen nur zu konfigurieren StudentAddress Entität wo StudentAddressId sollte ForeignKey sein.

Im folgenden Beispiel wird eine Eins-zu-Null oder Eins-Beziehung zwischen Schüler und StudentAddress Verwendung fliessend API.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{

    // Configure Student & StudentAddress entity
    modelBuilder.Entity<Student>()
                .HasOptional(s => s.Address) // Mark Address property optional in Student entity
                .WithRequired(ad => ad.Student); // mark Student property as required in StudentAddress entity. Cannot save StudentAddress without Student

}

Im obigen Beispiel wird Student Einheit konfiguriert mit HasOptional () -Methode, der anzeigt, dass die StudentAddress Navigationseigenschaft in Studenten Einheit optional ist (nicht erforderlich, wenn Schüler Entität zu speichern). Dann WithRequired () -Methode konfiguriert StudentAddress Einheit und make Studentennavigationseigenschaft von StudentAddress nach Bedarf (erforderlich, wenn StudentAddress Einheit zu speichern. Es wird eine Ausnahme ausgelöst, wenn StudentAddress Einheit ohne Studentennavigationseigenschaft Speicher wird). Dies wird auch als StudentAddressId ForeignKey machen.

Sie können also One-to-Zero-oder-eins-Beziehung zwischen zwei Einheiten konfigurieren, in denen Schüler Einheit ohne Befestigung StudentAddress Objekt, um es gespeichert werden kann, aber StudentAddress Einheit kann nicht ohne Anbringen eines Objekts von Studenten Einheit gespeichert werden. Dies macht ein Ende erforderlich.

Wenn StudentAddress Unternehmen nicht folgen Konventionen:
Nun lassen Sie uns ein Beispiel für StudentAddress Einheit, wo es nicht Primärschlüssel Konvention folgt das heißt unterschiedliche Id-Eigenschaft Namen haben als Id. Betrachten Sie die folgenden Schüler und StudentAddress Einheiten.

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    public int StudentId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

So, jetzt müssen wir configure StudentID Eigenschaft StudentAddress für PrimaryKey von StudentAddress sowie ForeignKey wie unten gezeigt.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure StudentId as PK for StudentAddress
    modelBuilder.Entity<StudentAddress>()
        .HasKey(e => e.StudentId);

    // Configure StudentId as FK for StudentAddress
    modelBuilder.Entity<Student>()
                .HasOptional(s => s.Address) 
                .WithRequired(ad => ad.Student); 

}

Konfigurieren One-to-One-Beziehung Fluent API:
Wir können One-to-One-Beziehung zwischen Einheiten konfigurieren mit Fluent API, wo beide Enden erforderlich sind, Objekt Studenten Einheit Bedeutung muss StudentAddress Entitätsobjekt und StudentAddress Einheit umfassen muss Objekt Studenten Einheit enthalten, um sie zu speichern.

Hinweis: One-to-one-Beziehung ist technisch nicht möglich, in MS SQL Server. Es wird immer eine Eins-zu-Null oder Eins sein. EF bildet One-to-One-Beziehungen zu Unternehmen, die nicht in DB.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure StudentId as PK for StudentAddress
    modelBuilder.Entity<StudentAddress>()
        .HasKey(e => e.StudentId);

    // Configure StudentId as FK for StudentAddress
    modelBuilder.Entity<Student>()
                .HasRequired(s => s.Address) 
                .WithRequiredPrincipal(ad => ad.Student); 

}

In dem obigen Beispiel modelBuilder.Entity (). HasRequired (s => s.Address) macht Adresse Eigenschaft StudentAddress erforderlich ist. .WithRequiredPrincipal (ad => ad.Student) macht Studenten Eigenschaft StudentAddress Einheit je nach Bedarf. So konfiguriert es beide erforderlich Ende. So, jetzt, wenn Sie versuchen, Studenten Entität zu speichern, ohne Adresse oder StudentAddress Einheit ohne Schüler, wird es eine Ausnahme aus.

Referenz: http: //www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top