views:

295

answers:

1

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?

+2  A: 

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.

mookid8000
Can I find the Cascade attribute in the FluentNHibernate assembly and should i decorate my class och property with this attribute?If it's not to much trouble it would be nice if you could show me with an example. Thanks
Marcus
You know what, I just wrote a post about this stuff: http://mookid.dk/oncode/archives/643 - actually, I did not know there was a `CascadeAttribute` in FNH, the one I'm talking about is my own. I don't know what the one in FNH does.
mookid8000
Sorry, didn't see the question mark there :) well, as you probably know by now: it's homemade
mookid8000
I sounds kinda weird that there is no native support for cascade saving in FNH, anyway I have included the CascadeConvention code in my project and without even using it in my configuration I get this error: The element 'class' in namespace 'urn:nhibernate-mapping-2.2' has incomplete content. List of possible elements expected: 'meta, subselect, cache, synchronize, comment, tuplizer, id, composite-id' in namespace 'urn:nhibernate-mapping-2.2'. This error appears just having the class in my project.
Marcus
mookid8000
Thanks for your help!
Marcus