I have a simple Fluent NHibernate model with two related classes:
public class Applicant
{
public Applicant()
{
Tags = new List<Tag>();
}
public virtual int Id { get; set; }
//other fields removed for sake of example
public virtual IList<Tag> Tags { get; protected set; }
public virtual void AddTag(Tag tag)
{
tag.Applicant = this;
Tags.Add(tag);
}
}
public class Tag
{
public virtual int Id { get; protected set; }
public virtual string TagName { get; set; }
public virtual Applicant Applicant { get; set; }
}
My fluent mapping is the following:
public class ApplicantMap : ClassMap<Applicant>
{
public ApplicantMap()
{
Id(x => x.Id);
HasMany(x => x.Tags).Cascade.All();
}
}
public class TagMap : ClassMap<Tag>
{
public TagMap()
{
Id(x => x.Id);
Map(x => x.TagName);
References(x => x.Applicant).Not.Nullable();
}
}
Whenever I try to update an applicant (inserting a new one works fine), it fails and I see the following SQL exception in the logs:
11:50:52.695 [6] DEBUG NHibernate.SQL - UPDATE [Tag] SET Applicant_id = null WHERE Applicant_id = @p0;@p0 = 37 [Type: Int32 (0)]
11:50:52.699 [6] ERROR NHibernate.AdoNet.AbstractBatcher - Could not execute command: UPDATE [Tag] SET Applicant_id = null WHERE Applicant_id = @p0 System.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'Applicant_id', table 'RecruitmentApp.dbo.Tag'; column does not allow nulls. UPDATE fails.
Why is NHibernate trying to update the tag table and set Applicant_id to null? I'm at a loss on this one.
Set Applicant.Tags
to Inverse
will instruct NHibernate to save Tags
after the Applicant
.
public class ApplicantMap : ClassMap<Applicant>
{
public ApplicantMap()
{
Id(x => x.Id);
HasMany(x => x.Tags).Cascade.All().Inverse();
}
}
More detail:
Inverse
(as opposed to .Not.Inverse()
) means the other side of the relationship (in this case, each Tag
) is responsible for maintaining the relationship. Therefore, NHibernate knows that the Applicant
must be saved first so that Tag
has a valid foreign key for its Applicant
.
Rule of thumb: The entity containing the foreign key is usually the owner, so the other table should have Inverse
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With