Invalid for root objects - use Delete instead

Invalid for root objects - use Delete instead

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


bniemyjski posted on Friday, June 26, 2009

Hello,

I'm getting the above exception (Invalid for root objects - use Delete instead), for an EditableChild called Cart.

[Serializable]
public partial class Cart : BusinessBase< Cart >

This EC is stored in an EditableChildList called CartList.

[Serializable]
public partial class CartList : BusinessListBase< CartList, Cart >

In a switchable object (Profile) I have a property declared:

private static readonly PropertyInfo<CartList> _shoppingCart = RegisterProperty<CartList>(p => p.ShoppingCart, Csla.RelationshipTypes.LazyLoad);

        public CartList ShoppingCart
        {
            get
            {
                if (!FieldManager.FieldExists(_shoppingCart))
                    SetProperty(_shoppingCart, CartList.GetCart(UniqueID, true));
               
                return GetProperty(_shoppingCart);
            }
        }

Inside of my CartList I have two methods:

/// <summary>
        /// Add an item to the cart.
        /// When ItemId to be added has already existed, this method will update the quantity instead.
        /// </summary>
        /// <param name="itemId">Item to add</param>
        /// <param name="uniqueID">Cart's Unique ID</param>
        /// <param name="isShoppingCart">Cart is a shopping cart.</param>
        public void Add(string itemId, int uniqueID, bool isShoppingCart)
        {
            int index = 0;
            bool found = false;

            foreach (Cart cart in this)
            {
                if (cart.ItemId == itemId)
                {
                    found = true;
                    break;
                }

                index++;
            }

            if (found)
                Items[index].Quantity += 1;
            else
            {
                Item item = Item.GetItem(itemId);
                Product product = Product.GetProduct(item.ProductId);
                Cart cart = Cart.NewCart();
                cart.UniqueID = uniqueID;
                cart.ItemId = itemId;
                cart.Name = item.Name;
                cart.ProductId = item.ProductId;
                cart.IsShoppingCart = isShoppingCart;
                cart.Price = item.ListPrice ?? item.UnitCost ?? 0;
                cart.Type = product.Name;
                cart.CategoryId = product.CategoryId;

                Add(cart);
            }
        }

        /// <summary>
        /// Remove item from the cart based on itemId.
        /// </summary>
        /// <param name="itemId">ItemId of item to remove</param>
        public void Remove(string itemId)
        {
            int index = 0;
            foreach (Cart cart in this)
            {
                if (cart.ItemId == itemId)
                    break;

                index++;
            }

            RemoveItem(index);
        }

The Add works as expected but the last line in the remove method throws the exception when the collection is saved. I noticed that the child is never marked as a child object like it should be. Do you guys have any ideas? I have already tried this.

Thanks
-Blake Niemyjski

RockfordLhotka replied on Friday, June 26, 2009

Unless you use the child data portal to create this object, you must manually call MarkAsChild().

bniemyjski replied on Friday, June 26, 2009

Tried that


Invalid operation - delete not allowed

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.NotSupportedException: Invalid operation - delete not allowed

Source Error:

Line 1388:    protected virtual void DataPortal_Delete(object criteria)
Line 1389: {
Line 1390: throw new NotSupportedException(Resources.DeleteNotSupportedException);
Line 1391: }
Line 1392:

.....
[DataPortalException: DataPortal.Update failed (Csla.DataPortalException: ChildDataPortal.Update failed on the server ---> Csla.Reflection.CallMethodException: Child_Update method call failed ---> Csla.DataPortalException: ChildDataPortal.Update failed on the server ---> Csla.Reflection.CallMethodException: Child_DeleteSelf method call failed ---> System.NotSupportedException: Invalid operation - delete not allowed
at Csla.Core.BusinessBase.DataPortal_Delete(Object criteria) in \Csla\Core\BusinessBase.cs:line 1390
at PetShop.Business.Cart.Child_DeleteSelf() in PetShop.Business\Entities\Cart.DataAccess.cs:line 62
at dm(Object , Object[] )

Any Ideas?

RockfordLhotka replied on Friday, June 26, 2009

If DataPortal_Delete() is being called it is because your code is calling DataPortal.Delete() to delete the object.

That's only valid on a root object, not a child object (technically - though the data portal won't prevent you from doing the wrong thing).

And if you do call DataPortal.Delete(), obviously you must implement DataPortal_Delete() for it to work. You are hitting the default implementation in the framework, which throws that exception to remind you to implement the method.

bniemyjski replied on Friday, June 26, 2009

Thanks Fixed it it just as you were typing :), The docs were not there for this..

RockfordLhotka replied on Friday, June 26, 2009

This is discussed in the Expert 2008 Business Objects book, where I talk about the difference between immediate and deferred deletion and how both models work in the framework and in your object models.

Copyright (c) Marimer LLC