2011-01-11 16 views
2

Ich versuche, eine Eins-zu-Eins-Zuordnung von meinen Benutzern zur Tabelle UserDetails einzurichten. Sagen, dass ich die folgenden Tabellen in meiner Datenbank haben:Zuordnung 1: 1-Zuordnung erlaubt kein Einfügen

Users: 

- UserID (PK, Identity) 
- UserName 
- Password 

UsersDetails: 

- UserID (PK, FK) 
- FirstName 
- LastName 

ich folgende poco Klassen erstellt haben:

public class User { 
    public virtual int UserID { get; set; } 
    public virtual string UserName { get; set; } 
    public virtual string Password { get; set; } 
    public virtual UserDetails Details { get; set; } 
} 

public class UserDetails { 
    public virtual int UserID { get; set; } 
    public virtual User User { get; set; } 
    public virtual string FirstName { get; set; } 
    public virtual string LastName { get; set; } 

    public UserDetails() { 
    } 

    public UserDetails(User user) { 
     User = user; 
    } 
} 

Welche fließend abgebildet werden (bitte die XML-Mapping beachten sehr ähnlich ist und wenn alles, was Sie wissen, die xML-Mapping ist dann würde ich schätzen Sie Führung noch):

public class UserMap : ClassMap<User> { 
    public UserMap() { 
     Table("Users"); 
     Id(x => x.UserID); 
     Map(x => x.UserName); 
     Map(x => x.Password); 
     HasOne(x => x.Details) 
      .Constrained() 
      .Cascade.All(); 
    } 
} 

public class UserDetailsMap : ClassMap<UserDetails> { 
    public UserDetailsMap() { 
     Table("UsersDetails"); 
     Id(x => x.UserID) 
      .GeneratedBy.Foreign("User"); 
     HasOne(x => x.User) 
      .Constrained(); 
     Map(x => x.FirstName); 
     Map(x => x.LastName); 
    } 
} 

Alles korrekt angezeigt, aber wenn ich sage:

var user = new User() { UserName = "Test", Password = "Test" }; 
user.Details = new UserDetails(user) { FirstName = "Test", LastName = "Test" }; 
session.Save(user); 

ich den Fehler:

"NHibernate.Id.IdentifierGenerationException: null ID erstellt für:. Userdetails"

Ich würde es wirklich schätzen, wenn mir jemand zeigen könnte, was ich falsch gemacht habe. Danke

Bearbeiten: Mit freundlicher Genehmigung von Jamie Ide's Vorschlag. Ich habe meine Benutzerzuordnung geändert:

public class UserMap : ClassMap<User> { 
    public UserMap() { 
     Table("Users"); 
     Id(x => x.UserID); 
     Map(x => x.UserName); 
     Map(x => x.Password); 
     References(x => x.Details, "UserID") 
      .Class<UserDetails>() 
      .Unique(); 
    } 
} 

Aber jetzt, wenn ich einen Benutzer einfügen bekomme ich den Fehler:

„System.ArgumentOutOfRangeException: Index war außerhalb des Bereichs muss nicht negativ sein und weniger als. die Größe der Sammlung. "

Wenn ich Cascade.All() zu meiner Referenz hinzufügen, erhalte ich den ursprünglichen Fehler, den ich über die erzeugte Null-ID erhielt.

Antwort

0

Nach weiterer Forschung scheint es, dass diese nicht in der Version 2.0 funktionieren. Ich bin jetzt in der Lage, auf Version 3.0 zu aktualisieren, wo ich glaube, dass dies jetzt möglich ist.

0

Ich bin mir nicht sicher, wie die Zuordnung der ID-Eigenschaft korrekt ist. sollte es nicht sein, nur eine autoincrement-ID und Ihr Mapping sollte wie folgt lauten:

Id(x=>x.UserId); 

Ich weiß nicht, die Idee hinter Foreign verwenden und wie es passt in die Dinge hier .. Sie bitte die Logik dahinter erläutern?

+0

Prost, aber das Feld UserID in der Tabelle UsersDetails ist ein Verweis auf die Tabelle Benutzer, die die automatisch inkrementierende ID enthält. Da es sich um eine Eins-zu-eins-Zuordnung handelt, ist die Benutzer-ID in der Tabelle UsersDetails auch der Primärschlüssel. Ich hoffe, das hilft. – nfplee

0

Ich denke, Sie müssen die Fremdschlüsselidentitätszuordnung in Ihrer Benutzerzuordnung anstelle der Benutzerdetails und der nativen in den UserDetails haben. Ich konnte jedoch keine Referenz dafür finden.

+0

Danke für Ihre Antwort. Ich habe gerade den folgenden Artikel gefunden (http://nhforge.org/blogs/nhibernate/archive/2011/01/08/composite-with-only-a-many-to-one-bad-idea.aspx) auf der NHibernate Blog. Es ist effektiv, was ich erreichen möchte, aber ich kann immer noch nicht sehen, wie meine Kartierung anders ist. – nfplee

2

Ich denke, Constrained sollte nur in der UserDetailsMap, nicht in der UserMap angegeben werden. Versuchen:

public class UserMap : ClassMap<User> { 
    public UserMap() { 
     Table("Users"); 
     Id(x => x.UserID); 
     Map(x => x.UserName); 
     Map(x => x.Password); 
     HasOne(x => x.Details) 
      .Cascade.All(); 
    } 
} 

EDIT:

Siehe this und this. Es scheint, dass Sie die Beziehung als viele-zu-eins von der Benutzerseite und eins-zu-eins-abhängig von der Seite UserDetails abbilden müssen, um Lazy Loading mit Eins-zu-Eins-Arbeit zu erreichen. Ich weiß nicht, ob das in NH3 anders ist.

+0

Cheers, aber das verzögerte Laden wird nicht unterstützt, wenn Sie in einer Eins-zu-eins-Beziehung keine Einschränkung angeben. – nfplee

+0

Nach weiterer Untersuchung. Es scheint, dass dies das Problem löst, aber Lazy Loading funktioniert immer noch nicht. Sobald ich die Benutzer ergreife, ergreift es auch die Details. – nfplee

+0

Nochmals vielen Dank, ich habe versucht, die User-Seite mit einer Zuordnung von vielen zu eins (ich habe meine ursprüngliche Frage mit dem neuen Mapping aktualisiert) versucht. Aber es funktioniert immer noch nicht. Ich würde Ihre Hilfe noch einmal sehr schätzen. Danke – nfplee

0

http://gorbach.wordpress.com/2010/09/24/fluent-onetoone/

HasOne(x => x.Details).Cascade.All().ForeignKey("UserDetails"); 
HasOne(x => x.User).Constrained(); 
var user = new User() { UserName = "Test", Password = "Test" }; 
user.Details = new UserDetails(user) { FirstName = "Test", LastName = "Test" }; 
user.Details.User = user; 
session.Save(user); 
Verwandte Themen