C# – Relation problems with Fluent NHibernate and Automappings

cfluent-nhibernate

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 session

2) Configure your Details collection to cascade

There 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 of IHasManyConvention and IReferenceConvention that checks for the presence of the attribute and sets the cascading option accordingly.

Related Topic