1

Zuerst habe ich eine Person Modell erstellt, die nur die grundlegenden Eigenschaften enthalten:EF nicht Tabellen aktualisieren, basierend auf meinem Modell

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

    [Required] 
    public string Firstname { get; set; } 

    [Required] 
    public string Lastname { get; set; } 

    [Required] 
    public Department Department { get; set; } 

    [Required] 
    public SourceType SourceType { get; set; } 

Nachdem ich bemerkte ich bin fehlt etwas, das ich habe eine neue Personen Eigenschaft hinzugefügt :

[Required] 
    public PersonData PersonData { get; set; } 

Leider EF wird die Datenbank überhaupt nicht aktualisieren - Personendaten, die zunächst ein Objekt des Typs Person enthalten aktualisiert wurde, so dass keine Person Eigenschaft mehr da ist. Auf der anderen Seite erstellt EF keine neue Spalte für PersonData_Id.

enter image description here

Zusätzlich wird die ID-Spalte ist nicht automatisch inkrementierende (alle ID-Spalte tun die anderen Tabelle). Was mich verwirrt, ist die folgende constraing, die in meiner Person Tabelle erstellt wird.

CONSTRAINT [FK_dbo.SGDB_Persons_dbo.SGDB_PersonData_Id] FOREIGN KEY ([Id]) LITERATUR [dbo] [SGDB_PersonData] ([Id])

Ich habe alles versucht (zumindest denke ich so). Ich habe alle Tabellen/die gesamte Datenbank manuell gelöscht, EF neu installiert, manuelle Migrationen ausgeführt, aber nichts scheint zu funktionieren.

Ich denke, es ist dieses Problem ist, die mich veranlasst nicht in der Lage sein, meine Datenbank mit dem folgenden Code auf Saatgut:

protected override void Seed(PersonContext context) { 
     base.Seed(context); 
     var dep = new DepartmentContext().Departments.First(); 

     var status = new Status("Test"); 
     var persondata = new PersonData(status); 
     context.Status.Add(status); 
     context.PersonData.Add(persondata); 
     for (int i = 0; i < 10; i++) { 
      var person = new Person { 
       Firstname = $"TestPersonFirstname{i}", 
       Lastname = $"TestPersonLastname{i}", 
       SourceType = COM.SourceType.Manual, 
       Department = dep, 
       PersonData = persondata 
      }; 
      context.Persons.Add(person); 
     } 
     context.SaveChanges(); 
    } 

Jedesmal diese ausgeführt Code get Ich erhalte eine Ausnahme:

Das Mitglied mit der Identität 'SGDB.DAL.Contexts.Person_Department' existiert nicht in der Metadatensammlung. Parametername: Identität.

Ich weiß nicht, ob beiden Probleme auf das gleiche Problem in Zusammenhang stehen, aber beide müssen gelöst werden :)

Vielen Dank im Voraus!

Update 1

ist meine Lösung in ein paar verschiedene Projekte aufgeteilt:

BLL, DAL, COM, UI

Datacontexts innerhalb des DAL-Projekt befinden, Modelle innerhalb des COM-Projekt .

Abteilung Modell:

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

    [Required] 
    public string Costcenter { get; set; } 

    [Required] 
    public string Abbreviation { get; set; } 

    public string Description { get; set; } 

    public string FullDepartmentName { 
     get { 
      return [email protected]"{Division.Abbreviation}\{Abbreviation}"; 
     } 
    } 
    [Required] 
    public virtual Division Division { get; set; } 
} 

Personen Modell:

[Table("SGDB_PersonData")] 
public class PersonData { 
    public PersonData(Status status) { 
     Status = status; 
    } 

    public int Id { get; set; } 
    public DateTime Limit { get; set; } 
    public Person Responsible { get; set; } 
    [Required] 
    public Status Status { get; set; } 
} 

Die Tabelle Person (wie man sehen kann) hat eine Spalte DEPARTMENT_ID bekam (EF automatisch eingefügt).

Klärung

Eine Person-Objekt enthält ein Personen Objekt als zusätzliche Informationen für diese Person. Eine Person hat möglicherweise eine verantwortliche Person (daher ist PersonData.Responsible keine Navigationseigenschaft für die übergeordnete Person). Zusätzlich, wenn möglich, möchte ich keinen fremden Schlüssel in der PersonData-Tabelle haben.

Als ich ich muss

ändern herausgefunden würde
modelBuilder.Entity<Person>() 
     .HasRequired(e => e.PersonData) 
     .WithRequiredPrincipal(e => e.Responsible) 
     .WillCascadeOnDelete(true); 

zu

modelBuilder.Entity<Person>() 
     .HasRequired(e => e.PersonData) 
     .WithMany() 
     .WillCascadeOnDelete(true); 

Ich werde dies versuchen und berichten, ob es mein Problem gelöst.

aktualisieren 2

Das Mitglied mit Identität 'SGDB.DAL.Contexts.Person_Department' existiert nicht in der Metadatensammlung.

+0

Ist PersonData im selben Projekt? Wie sieht dein Kontext aus? –

+0

Bitte schließen Sie "Department" - und "PersonData" -Modelle ein. Klingt nach Beziehungskonfigurationsproblemen. –

+0

@SteveGreene - siehe meine Frage für aktuelle Informationen. – C4p741nZ

Antwort

1

Ihr Modell definiert one-to-one Beziehung zwischen Person und PersonData mit später erforderlich ist und der ehemaligen - optional. EF verwendet immer die erforderliche Seite der one-to-one-Beziehung als Prinzip und optionalen Teil wie abhängig. Daher denkt es PersonaData ist das Prinzipal und Person - abhängig und spiegelt das im Datenbanktabellenentwurf wider.

Sie benötigen das Gegenteil und auch beide Seiten erforderlich. Wenn beide Seiten erforderlich oder optional sind, kann EF nicht automatisch die prinzipielle/abhängige Seite ableiten, und es gibt keine Möglichkeit, dies über Datenannotationen (Attribute) anzugeben, sodass Sie eine flüssige API-Einrichtung benötigen.

außer Kraft setzen Ihre DbContext OnModelCreating und so etwas wie hinzufügen:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Person>()    
     .HasRequired(e => e.PersonData) 
     .WithRequiredPrincipal(e => e.Responsible) 
     .WillCascadeOnDelete(true); 

    base.OnModelCreating(modelBuilder); 
} 

Was sie tut, ist EF zu sagen, dass beide Seiten der Person->PersonData Beziehung erforderlich sind und Person ist das wichtigste. Dies sollte wieder Ihre Person.Id Spalte Auto-Inkrement machen und sollte den Personendaten Teil des Problems auflösen.

Die andere Sache, die ich bemerkt habe, ist diese Zeile:

var dep = new DepartmentContext().Departments.First(); 

während alle anderen Teile des gleichen Verfahrens werden eine Variable context genannt werden. Das könnte/könnte kein Problem sein, schau es dir einfach an.

UPDATE: Von der Klärung in der aktualisierten Frage stellt sich heraus, Sie zwei Beziehungen zwischen Person und PersonData haben, so dass Sie für jeden von ihnen, wie diese getrennte Konfiguration benötigen:

modelBuilder.Entity<Person>() 
    .HasRequired(e => e.PersonData) 
    .WithRequiredPrincipal() 
    .WillCascadeOnDelete(true); 

modelBuilder.Entity<PersonData>() 
    .HasOptional(e => e.Responsible) 
    .WithOptionalDependent() // or WithMany() 
    .WillCascadeOnDelete(false); 

Bitte beachten dass es keine Möglichkeit gibt, keine zusätzliche FK-Säule in die PersonData Tabelle einzuführen. Es wird benötigt, um die Responsible Beziehung darzustellen, so dass Sie mit einer Tabellenspalte namens Responsible_Id enden.

+0

Ich werde das morgen versuchen. Für den letzten Teil: Da Abteilung und Person unterschiedliche Kontexte haben, muss ich beim Seeding eine Abteilung aus der Datenbank bekommen und sie in mein neues Personenobjekt einfügen - ist das der richtige Versuch oder sollte es anders gemacht werden? Was den ersten Teil betrifft, habe ich vergessen zu erwähnen, dass selbst die PersonData-Tabelle keine Spalte für eine Person_ID hat (Ich werde dies überprüfen, sobald ich meine Datenbank sehen kann) – C4p741nZ

+1

Es wird nicht - siehe [Geteilte primäre Key Associations] (http://weblogs.asp.net/manavi/associations-in-ef-4-1-code-first-part-3-shared-primary-key-associations) –

+0

Ok, ich habe deinen Beitrag gelesen noch einmal und ich denke, ich muss klarstellen, dass die Verantwortliche Person * nicht * das ursprüngliche Person-Objekt ist. Eine Person enthält PersonData - PersonData.Responsible könnte null sein, wenn die Person keine verantwortliche Person hat (weil dieser Verantwortliche nicht erforderlich ist). – C4p741nZ

Verwandte Themen