I'm new to NHibernate and I'm creating a simple scenario to test the framework functionalities.
I have to basic entities:
public class School : BaseEntity
{
public virtual string Code { get; set; }
public virtual string Name { get; set; }
}
public class Student : BaseEntity
{
public virtual string Name { get; set; }
public virtual string Surname { get; set; }
public virtual string Email { get; set; }
public virtual School School { get; set; }
}
inheriting from a simple base class:
public abstract class BaseEntity
{
public virtual int Id { get; protected set; }
}
Than I map entities using FluentNhibernate this way:
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012.ConnectionString(
c => c.FromConnectionStringWithKey("DataModel")))
.Mappings(m => m.AutoMappings
.Add(AutoMap.AssemblyOf<BaseEntity>()
.Where(t => t.Namespace == "MyApp.Models"))
.IgnoreBase<BaseEntity>()
.Override<User>(map =>
{
map.Table("Users");
map.HasOne<School>(u => u.School).ForeignKey("SchoolId");
})
.Override<School>(map =>
{
map.Table("Schools");
})
))
.BuildSessionFactory();
My test code is very simple:
using (var transaction = DbSession.BeginTransaction())
{
Student u1 = DbSession.Get<Student>("user-id");
School s1 = DbSession.Get<School>("school-id");
u1.School = s1; // updating the associated school
DbSession.SaveOrUpdate(u1);
transaction.Commit(); // !!! the foreign key is not updated
}
Checkign the Students table, the row is not updated with the new school id.
So, what's wrong in my code? Is there something incorrect (or missing) in my mappings?
A Student
belonging to the School
is a many-to-one
relationship.
An ordinary association to another persistent class is declared using a many-to-one element. The relational model is a many-to-one association. (It's really just an object reference.)
Its fluent version is .References()
References is for creating many-to-one relationships between two entities, and is applied on the "many side." You're referencing a single other entity, so you use the References method. #HasMany / one-to-many is the "other side" of the References relationship, and gets applied on the "one side."
Let's map a relationship between a book and its author.
public class Book
{
public Author Author { get; set; }
}
public class Author
{
public IList<Book> Books { get; set; }
}
In domain terms, we have an Author which may be associated with any number of Books, and Books, each of which can be associated with a single Author.
In database terms, we'd have a book table with a foreign key column referencing the primary key of an author table.
To create the references relationship in your Book #ClassMap, add the following call in the BookMap constructor:
References(x => x.Author);
Other words, if we need the many-to-one
relationship to be mapped with fluent, we cannot use .HasOne()
but .References()
//map.HasOne<School>(u => u.School).ForeignKey("SchoolId");
map.References(u => u.School, "SchoolId");
To get full overview of the .References() API, read the second half of this article (the first half is bout mapping by code, the second is comparison with fluent):
Note - what is the .HasOne()
(the one-to-one
) scenario issues could be found here