Fluent NHibernate: How to have a one-to-many reference in both directions?
We have Users on our system and Persons. There are many Persons for each User. But when a user logs on, we need to look up his primary Person record to fill in his name, address, phone, etc.
public class Per开发者_如何学Cson
{
/// <summary>Every Person belongs to a user.</summary>
public virtual User User { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Address { get; set; }
public virtual string Phone { get; set; }
// More methods & Properties
}
public class User : Entity
{
public virtual string Username { get; set; }
public virtual string Password { get; set; }
/// <summary>Every User has a primary person record.</summary>
public virtual Person PrimaryPerson { get; set; }
// More methods & Properties
}
How does the class map look for this without a circular reference?
Try this:
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Table("Persons");
Id(x =>x.Id, "PersonId").GeneratedBy.Identity();
References(x => x.User).Column("UserId").Cascade.All();
Map(x => x.FirstName, "FirstName");
Map(x => x.LastName, "LastName");
Map(x => x.Address, "Address");
Map(x => x.Phone, "Phone");
// More property maps
}
}
public class UserMap : ClassMap<User>
{
public UserMap()
{
Id(x => x.Id, "UserId").GeneratedBy.Identity();
Map(x => x.Username, "Username");
Map(x => x.Password, "Password");
References<Person>(x => x.PrimaryPerson).ForeignKey("PrimaryPersonId").Cascade.All();
}
}
This is assuming your Ids are autonumber and that when you update a User, you also want your PrimaryPerson to be updated along with it. Change the Cascade.All() to Cascade.None() if that isn't the case. Just be sure that when you do, you update the PrimaryPerson manually or you'll get a "object references an unsaved transient instance" upon SubmitChanges() if you don't.
Based on my comment on your question, I think the mapping would be something along the lines of:
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.Id)...
...
References(x => x.User).Inverse(); // User references Person
}
}
public class UserMap : ClassMap<User>
{
public UserMap()
{
Id(x => x.Id)...
...
References(x => x.PrimaryPerson).Column("PrimaryPersonId")...
HasMany(x => x.People).KeyColumn("UserId").Inverse(); // UserId is on the Person
}
}
Edit: Added Table Structure.
[User]
UserId
... -- Other Columns
PrimaryPersonId -- FK to PersonId in Person table
[Person]
PersonId
... -- Other Columns
UserId -- FK to UserId in User Table for user has many Persons.
精彩评论