klkitchens
klkitchens

Reputation: 1242

nHibernate Mapping issue -- Nulling, not deleting children and grandchildren

Blockquote

We are using the ByCode method of mapping our data..

I have Process (Process table) object which has a List of ProcessStep (ProcessStep table) objects which in turn has a Bag of ProcessStepUser (ProcessStepUser table) objects assigned to each step.

The objects load just fine, but in the web page if I delete a Step from the collection, rehydrate into MVC action as a Process and then save the process, the Step in the database simply has the ProcessId set to null which breaks the link, but leaves the Step in the Database and all its assigned users.

What I want to be able to do is delete a Step and have its ProcessStep and all its ProcessStepUsers deleted.

Likewise, when I edit a ProcessStep (say I change the name of the step) and save, it's saving that, but the ProcessStep users are nulled out (of their ProcessStepId) and recreated, leaving orphaned records.

I do have a column on ProcessStepUser for overall ProcessId as well, so that I can prevent a User from being assigned more than once to any step of the process.

My relevant mapping is as follows:

Process:

            List(x => x.ProcessSteps, m =>
                           {
                               m.Key(k => k.Column("ProcessId"));
                               m.Index(i => i.Column("StepOrder"));
                               m.Lazy(CollectionLazy.NoLazy);
                               m.Cascade(Cascade.All);
                       m.Inverse(false);
                           },
             r => r.OneToMany(o => o.Class(typeof (ProcessStep))));

ProcessStep:

            Bag(x => x.ProcessStepUsers, m =>
        {
            m.Key(k => k.Column("ProcessStepId"));
            m.Lazy(CollectionLazy.NoLazy);
            m.Cascade(Cascade.All);
            m.Inverse(false);
        },
        r => r.OneToMany(o => o.Class(typeof (ProcessStepUser))));
        ManyToOne(x => x.Process, m =>
        {
            m.Column("ProcessId");
            m.Class(typeof (Process));
                     });

ProcessStepUser

            ManyToOne(p => p.Step, m =>
                               {
                                   m.Column("ProcessStepId");
                                   m.Class(typeof (ProcessStep));
                               });
        ManyToOne(p => p.Process, m =>
        {
            m.Column("ProcessId");
            m.Class(typeof (Process));
        });

As I said, it saves just fine on creation and loads just fine for display. But the dropping of a step or editing of a step is creating havoc in the Database.

I hacked the step deletion process by flagging them and manually deleting them before saving the Process master object, but I'd like nhibernate to do it all if possible.

Thanks!

Blockquote

First off thanks to Martin who caught the one issue with the Cascade.All.Include(Cascade.DeleteOrphans)... that was the original code I had, I forgot I'd changed it while attempting to solve the problem.

I rewrote some tests and the mapping actually is working just fine, so apologies there. I would delete this question, but the site is not letting me to anything (in Firefox) but edit...

The problem ended up being because I was getting the Process object from the database and then serializing it up to the View as a JSON object. I then passed back the JSON object which was bound back to the Process object.

The long and short is that our repository was calling SaveOrUpdate(obj) on the object, but since it had been disconnected, we needed to call Merge(obj) which we did and worked perfectly.

I leave it to the powers that be as to whether this question has any value remaining.

Thanks!

Upvotes: 0

Views: 163

Answers (1)

Martin Ernst
Martin Ernst

Reputation: 5679

Try Cascade(Cascade.AllDeleteOrphan) on your associations where you want them to be deleted instead of having the other side nulled...

Upvotes: 1

Related Questions