Karl Cassar
Karl Cassar

Reputation: 6473

collection cascade type in nhibernate

I am using NHibernate 3.2, and using Mapping by Code.

The test case is pretty straight-forward - I have a Store and a Product, linked by a many-to-many collection. The many-to-many collection in the StoreMap is mapped as follows:

Set(x => x.Products, x =>
        {
            x.Fetch(CollectionFetchMode.Subselect);
            x.Key(key =>
            {
                key.Column("StoreId");
                key.ForeignKey("FK_StoreProducts_Store");
            });
            x.Table("StoreProducts");
            x.Cascade(Cascade.None);
            x.Inverse(true);

        },

If I am correct, the Cascade option should allow you to choose whether you want to cascade operations on the class, to the collection as well. NHibernate 3.2 allows these options, which are not really straightforward for me:

[Flags]
public enum Cascade
{
    None = 0,
    Persist = 2,
    Refresh = 4,
    Merge = 8,
    Remove = 16,
    Detach = 32,
    ReAttach = 64,
    DeleteOrphans = 128,
    All = 256,
}

The example I am using is the one below, where I am creating a test Store, and a test Product, and assigning it to the store. Then I am reloading the Store, retrieving the first Product, updating it, and saving the Store.

Even though the cascade is set as 'None', the Product still updates! Is it normal that this should happen?

using (var session = SessionFactory.OpenSession())
        {
            long storeId = 5;
            using (var t = session.BeginTransaction())
            {
                Product p1 = new Product();
                p1.Name = "Product 1";
                session.Save(p1);

                Store store = new Store();
                store.Name = "Tesco";
                session.Save(store);

                p1.Stores.Add(store);
                store.Products.Add(p1);
                session.Save(store);

                storeId = store.Id;
                t.Commit();
            }

            using (var t = session.BeginTransaction())
            {
                Store s = session.Get<Store>(storeId);
                Product p = s.Products.FirstOrDefault();
                p.Name = "Product 1 Updated";
                session.Save(s);
                t.Commit(); // <-- Product is still being updated here!

            }
            session.Flush();
        }

Upvotes: 0

Views: 676

Answers (1)

Sly
Sly

Reputation: 15217

Feature that you are facing is called change tracking, and has nothing to do with cascading options. NHibernate tracks all objects that are associated with a session and sends all changes to DB when transaction is committed.

If you don't need it you can use Stateless session in order to get non tracked entities. But in this case you will not have lazy loading. Also you can try to use FlushMode.Never in order to prevent NHibernate from automatic flushing changes to DB

Upvotes: 1

Related Questions