I have made a simple example application to test Fluent NHibernate with the automapping feature but I get an exception when I save.
This is how my example looks like:
public class Item {
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual IList<Detail> Details { get; set; }
public Item() {
Details = new List<Detail>();
}
}
public class Detail {
public virtual int Id { get; protected set; }
public virtual int ItemId { get; set; }
public virtual string Name { get; set; }
}
class Program {
static void Main(string[] args) {
var sessionFactory = CreateSessionFactory();
using (var session = sessionFactory.OpenSession()) {
using (var transaction = session.BeginTransaction()) {
Console.WriteLine("Enter name for new item: ");
var itemName = Console.ReadLine();
var page = new Item { Name = itemName };
Console.WriteLine("Enter name of new detail");
var detailName = Console.ReadLine();
var detail = new Detail {Name = detailName };
page.Details.Add(detail);
session.SaveOrUpdate(page);
transaction.Commit();
}
using (session.BeginTransaction()) {
}
Console.ReadKey();
}
}
private static ISessionFactory CreateSessionFactory() {
var model = AutoMap.AssemblyOf<Program>();
var sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(connection)
.Cache(c => c.UseQueryCache()
.ProviderClass<HashtableCacheProvider>())
.ShowSql())
.Mappings(m => m.AutoMappings.Add(model))
.BuildSessionFactory();
return sessionFactory;
}
}
This code throws an exception when transaction.Commit() is running and the exception is object references an unsaved transient instance – save the transient instance before flushing.
So can anybody help me figure out what's wrong?
Best Answer
Your
detail
instance is "transient", which means that is has not been added to your NHibernate session.You have two option, where #2 is probably preferred in your case:
1)
session.Save(detail)
before you flush the session2) Configure your
Details
collection to cascadeThere are many ways to configure cascading when you are using the automapping feature - I usually prefer to "pollute" my domain model with
[Cascade]
attributes, and then create a simple implementation ofIHasManyConvention
andIReferenceConvention
that checks for the presence of the attribute and sets the cascading option accordingly.