Why can't I just insert the model after I get an error back from the database when trying to insert it the first time:
Report report = null;
using (var session = SessionFactory.OpenSession()) {
try {
using (var transaction = session.BeginTransaction()) {
report = new Report();
session.SaveOrUpdate(report);//Exception: Name field required
transaction.Commit();
}
}
catch { }
try {
using (var transaction = session.BeginTransaction()) {
report.Name = "theName";
session.SaveOrUpdate(report);
//Causes Exception:
//Row was updated or deleted by another transaction (or unsaved-value
//mapping was incorrect): [ReportViewer.DataAccess.Models.Report#22]
transaction.Commit();
}
}
catch { }
}
But when I am updating an existing model, and I get an error, I can make my fixes (in this case set a Name) and just try to update again:
Report report = null;
using (var session = SessionFactory.OpenSession()) {
using (var transaction = session.BeginTransaction()) {
report = new Report();
report.Name = "theName";
session.SaveOrUpdate(report);
transaction.Commit();
}
}
using (var session = SessionFactory.OpenSession()) {
//get entity saved from previous session
report = session.Get<Report>(report.Id);
try {
using (var transaction = session.BeginTransaction()) {
report.Name = null;
session.SaveOrUpdate(report);//Exception: Name field required
transaction.Commit();
}
}
catch { }
try {
using (var transaction = session.BeginTransaction()) {
//updates and does not give an error
report.Name = "theName";
session.SaveOrUpdate(report);
transaction.Commit();
}
}
catch { }
}
As Oskar said, you should discard an NHibernate session after an exception occurs. However, the reason the insert fails is that you have already made the report persistent by calling SaveOrUpdate
on it (you should use Save
here). When you call SaveOrUpdate
again on the same instance, NHibernate throws an exception because the object is already persistent. Rewriting the code as follows will probably allow the insert to succeed (but it's not recommended):
try {
using (var transaction = session.BeginTransaction()) {
report.Name = "theName";
transaction.Commit();
}
}
In the update example, calling SaveOrUpdate
has no effect because the object became persistent when NHibernate loaded it. Understanding NHibernate's instance states and how to work with persistent objects is fundamental and widely misunderstood.
A far better approach is to validate your objects before saving them to the database.