I'm using Fluent NHibernate in an attempt to improve testability and maintainability on a web application that is using a legacy database and I'm having some trouble mapping this structure properly:
I have two tables that really represent one entity in the domain, and so I'm using a join to map them as such, and a third table that represents a second entity.
DB Tables:
[eACCT]
ACCT_ID
ACCT_NAME
[eREPORT_TYPE]
ACCT_ID
REPORT_NO
[eREPORT_TYPE_DESC]
REPORT_NO
REPORT_TYPE
Entities:
public class Account
{
public virtual string AccountID { get; set; }
public virtual string AccountName { get; set; }
public virtual ReportType ReportType { get; set; }
}
public class ReportType
{
public virtual int Number { get; set; }
public virtual string Type { get; set; }
}
Mapping:
public AccountMap()
{
Table("eACCT");
Id(x => x.AccountID, "ACCT_ID");
Map(x => x.AccountName, "ACCT_NAME");
Join("eREPORT_TYPE", m =>
{
m.KeyColumn("ACCT_ID");
m.References(x => x.ReportType)
.Cascade.None()
.Column("REPORT_NO");
});
}
public ReportTypeMap()
{
Table("eREPORT_TYPE_DESC");
Id(x => x.Number)
.Column("REPORT_NO")
.GeneratedBy.Assigned();
Map(x => x.Type, "REPORT_TYPE");
}
This works fine for my Gets, but when I modify Account.ReportType.Number and then SaveOrUpdate() Account, I get the error: 'identifier of an instance of DataTest.Model.ReportType was altered from (old_value) to (new_value)'.
All I want to do is modify Account's reference to ReportType and I thought that by setting the Cascade.None() property on the reference to ReportType, NHibernate wouldn't attempt to save the ReportType instance as well, but I must be misunderstanding how that works. I've tried making ReportType ReadOnly(), making the reference to ReportType ReadOnly(), etc and nothing seems to help.
Any ideas?
Finally solved this problem. Turns out I wasn't thinking about this in an NHibernate way. In my mind I had a new ReportType.Number, so that's what I needed to update. In reality, what I needed to do was get the ReportType with the new ReportType.Number and set the Account.ReportType. Doing it this way worked as expected.