Problem with DynamicListBase Remove when save fails

Problem with DynamicListBase Remove when save fails

Old forum URL: forums.lhotka.net/forums/t/10232.aspx


RSinden posted on Monday, April 04, 2011

Hi,

I'm using CSLA.NET 4.0, and I have basically the same problem as described in this old post: http://forums.lhotka.net/forums/p/3548/17619.aspx.

To summarise, I have a list based on DynamicListBase, and I'm calling Remove to get rid of one of my items. The delete on the item is failing for valid reasons (e.g. database constraints). I'm getting the saved event on the list with the error property set appropriately. The problem is that I am now left with an item in the list with IsDeleted set to true.

The original problem was apparently fixed by doing some cloning in SaveItem, but the problem here is that Delete has already been called in RemoveItem, before it calls SaveItem, so the item is being cloned after this.

To solve this problem without modifying the CSLA code, I'm cloning the item myself before calling remove, storing it, and then, in the saved event handler, replacing the Deleted item with the cloned one if there was an error.

Whilst my workaround seems to do the trick, it seems to me that as the CSLA code marked it as deleted, it should really be undoing this when the save failed. What are your thoughts?

Thanks,

Rich

RockfordLhotka replied on Tuesday, April 05, 2011

This does seem like a bug. Can you provide a very simple unit test style bit of code to illustrate the issue?

RSinden replied on Tuesday, April 05, 2011

Yep, here you go...

using Csla;
using System;
using System.Diagnostics;
using System.Threading;

namespace DLBRemoveErrorTest
{
    [Serializable]
    class Thing : BusinessBase<Thing>
    {
        public bool ThrowExceptionOnDelete { get; set; }

        protected override void DataPortal_Insert()
        { }

        protected override void DataPortal_DeleteSelf()
        {
            if (ThrowExceptionOnDelete)
            {
                throw new Exception();
            }
        }
    }

    class ListOfThings : DynamicListBase<Thing>
    { }

    class Program
    {
        static AutoResetEvent _moveOn = new AutoResetEvent(false);
        static void Main(string[] args)
        {
            ListOfThings things = new ListOfThings();
            things.Saved += things_Saved;

            // add a couple of items - set up first one to work, second one to fail
            Thing thing1 = things.AddNew();
            thing1.ThrowExceptionOnDelete = false;
            Thing thing2 = things.AddNew();            
            thing2.ThrowExceptionOnDelete = true;
            
            // save both items
            things.SaveItem(thing1);
            _moveOn.WaitOne();        
            things.SaveItem(thing2);
            _moveOn.WaitOne();
            Debug.Assert(things.Count == 2);            
            
            // remove the first one - this should work
            things.Remove(things[0]);
            _moveOn.WaitOne();
            Debug.Assert(things.Count == 1);

            // attempt to remove the second one
            // - this should fail and I would expect it to be left in the list in the same state it was in before
            Debug.Assert(!things[0].IsDeleted);    
            things.Remove(things[0]);
            _moveOn.WaitOne();
            Debug.Assert(things.Count == 1);            
            // check it is still not deleted - This is the problem
            Debug.Assert(!things[0].IsDeleted);

            things.Saved -= things_Saved;
        }

        static void things_Saved(object sender, Csla.Core.SavedEventArgs e)
        {
            _moveOn.Set();
        }
    }
}

RockfordLhotka replied on Tuesday, April 05, 2011

Thank you, that's great! I have added this to the bug list.

Copyright (c) Marimer LLC