Connot save "copied" entity

Posts   
 
    
Noer
User
Posts: 33
Joined: 04-Jan-2007
# Posted on: 21-Mar-2007 14:24:17   

Hi,

I have 2 windows-user-controls, one called order and one called car. The order control contains 10 car controls (displayed in tab view). A car control contains information like manufacturer, model, registration number aso. From the order control you can "copy" the content of one car control to other car controls, but when I try to save the order (containing the cars) it fails when it try to save the copied car, and I get the following error:

An exception was caught during the execution of an action query: Cannot insert the value NULL into column 'OrderID', table 'BiludanBTK.dbo.Car'; column does not allow nulls. INSERT fails.

The statement has been terminated.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception.
System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'OrderID', table 'BiludanBTK.dbo.Car'; column does not allow nulls. INSERT fails.

The statement has been terminated.

   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)

   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)

   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)

   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)

   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)

   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)

   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)

   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)

   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()

   at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute()

I have debugged and the CarEntity that fails to be saved have an OrderID.

This is the code that copies the values:

private void but_copyCars_Click(object sender, EventArgs e)
        {
            CarCopyEntity carToCopy = ((Car)tab_cars.Controls.Find("uc_car" + (_carIndesToCopy + 1).ToString(), true)[0]).UnbindCarValuesForCarCopy();

            for (int i = 1; i <= 10; i++)
            {
                CheckBox chkBox = (CheckBox)pan_copyCar.Controls.Find("chk_copyToCar" + i.ToString(), true)[0];

                if ((chkBox.Enabled) && (chkBox.Checked))
                {
                    ((Car)tab_cars.Controls.Find("uc_car" + i.ToString(), true)[0]).BindCarValues(carToCopy);
                }
            }
            UpdatePrices(sender, e);
            pan_copyCar.Visible = false;
        }

This Unbinds the values:

public CarCopyEntity UnbindCarValuesForCarCopy()
        {
            CarCopyEntity carCopy = new CarCopyEntity();

            if ((com_carModel.Enabled) && (com_carModel.SelectedItem != null) && (((CarModelEntity)com_carModel.SelectedItem).CarModelID != Guid.Empty))
                carCopy.CarModel = (CarModelEntity)com_carModel.SelectedItem;
            else
                carCopy.CarModel = null;
            carCopy.RegMva = txt_regMva.Text;
            if (chk_extraFeeLarge.Checked)
                carCopy.CarTypeID = (int)CarType.Large;
            else if (chk_extraFeeSmall.Checked)
                carCopy.CarTypeID = (int)CarType.Small;
            else
                carCopy.CarTypeID = null;
            carCopy.ExpressDelivery = chk_expressDelivery.Checked;
            if (chk_difrentDestinationAddressOnInvoice.Checked)
                carCopy.Address = ((ComboAddress)com_invoiceDestinationAddress.SelectedItem).Address;
            else
                carCopy.Address = null;

            if ((com_FromAddress.SelectedItem != null) && (((ComboAddress)com_FromAddress.SelectedItem).Address.AddressID != Guid.Empty))
                carCopy.PickupAddress = (ComboAddress)com_FromAddress.SelectedItem;

            if ((com_ToAddress.SelectedItem != null) && (((ComboAddress)com_ToAddress.SelectedItem).Address.AddressID != Guid.Empty))
                carCopy.DestinationAddress = (ComboAddress)com_ToAddress.SelectedItem;

            if ((com_Reloading1.SelectedItem != null) && (((AddressEntity)com_Reloading1.SelectedItem).AddressID != Guid.Empty))
                carCopy.Reloading1 = (AddressEntity)com_Reloading1.SelectedItem;

            if ((com_Reloading2.SelectedItem != null) && (((AddressEntity)com_Reloading2.SelectedItem).AddressID != Guid.Empty))
                carCopy.Reloading2 = (AddressEntity)com_Reloading2.SelectedItem;

            carCopy.CommentPublic = txt_commentPublic.Text;
            carCopy.CommentInternal = txt_commentInternal.Text;

            return carCopy;
            
        }

And this binds the values:

public void BindCarValues(CarCopyEntity car)
        {
            _disablePriceCalc = true;
            if (car.CarModel.CarModelID != Guid.Empty)
            {
                com_carManufacturer.SelectedItem = car.CarModel.CarManufacturer;
                com_carModel.SelectedItem = car.CarModel;
            }
            txt_regMva.Text = car.RegMva;
            chk_extraFeeSmall.Checked = (car.CarTypeID == (int)CarType.Small);
            chk_extraFeeLarge.Checked = (car.CarTypeID == (int)CarType.Large);
            chk_expressDelivery.Checked = car.ExpressDelivery;
            if ((car.InvoiceDestinationID.HasValue) && (car.InvoiceDestinationID.Value != Guid.Empty))
            {
                chk_difrentDestinationAddressOnInvoice.Checked = true;
                com_invoiceDestinationAddress.SelectedItem = new ComboAddress(car.Address);
            }

            if ((car.PickupAddress != null) && (car.PickupAddress.Address.AddressID != Guid.Empty))
                com_FromAddress.SelectedItem = car.PickupAddress;

            if ((car.DestinationAddress != null) && (car.DestinationAddress.Address.AddressID != Guid.Empty))
                com_ToAddress.SelectedItem = car.DestinationAddress;

            if ((car.Reloading1 != null) && (car.Reloading1.AddressID != Guid.Empty))
                com_Reloading1.SelectedItem = car.Reloading1;

            if ((car.Reloading2 != null) && (car.Reloading2.AddressID != Guid.Empty))
                com_Reloading2.SelectedItem = car.Reloading2;

            txt_commentInternal.Text = car.CommentInternal;
            txt_commentPublic.Text = car.CommentPublic;

            UpdateDispatchList();
            _disablePriceCalc = false;
        }

If I add more cars manually there is no problem.

Where should I look to solve this?

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 21-Mar-2007 14:33:23   

I can't see where the OrderId of the copied car is being set.

All I see from the code posted is that you copy data from textboxes (controls) of one tab to those of another tab.

How do you save the Copied Car? Do you Add it to the Order.CarCollection afterwards so it takes the OrderId from this association?

Noer
User
Posts: 33
Joined: 04-Jan-2007
# Posted on: 21-Mar-2007 14:37:51   

Yes the cars are added to a collection. When I save this is called:

private void UnbindOrderValues()
        {
            if ((_order.IsNew) && (_order.OrderID == Guid.Empty))
                _order.OrderID = Guid.NewGuid();
                        
            if (com_customer.SelectedItem != null)
                _order.Customer = ((ComboCustomer)com_customer.SelectedItem).Customer;
            else
                _order.Customer = null;
            if (rad_priceTypeNormal.Checked)
                _order.PriceTypeID = (int)OrderPriceType.Normal;
            else if (rad_priceTypeFixed.Checked)
            {
                _order.PriceTypeID = (int)OrderPriceType.Fixed;
                decimal? orderPrice = BTK.Services.ParseHelper.ParseDecimal(txt_price.Text);
                if (orderPrice.HasValue)
                    _order.Price = orderPrice.Value;
                else
                    _order.Price = -1;
            }
            else if (rad_priceTypeFullLoad.Checked)
                _order.PriceTypeID = (int)OrderPriceType.FullLoad;
            else if (rad_priceTypeNordania.Checked)
                _order.PriceTypeID = (int)OrderPriceType.Nordania;

            _order.UseCustomerDiscount = chk_discount.Checked;
            
            if (_order.PriceTypeID == (int)OrderPriceType.FullLoad)
            {
                _order.FullLoadPickupAreaDefinition = ((ComboArea)com_fullLoadPickupArea.SelectedItem).AreaDefinition;
                _order.FullLoadDesternationAreaDefinition = ((ComboArea)com_fullLoadDestinationArea.SelectedItem).AreaDefinition;
            }
            else
            {
                _order.FullLoadPickupAreaDefinition = null;
                _order.FullLoadDesternationAreaDefinition = null;
            }

            _order.CustomerRef = txt_customerRef.Text;
            
            if ((com_commission.SelectedItem != null) && (((CommissionEntity)com_commission.SelectedItem).CommissionID != Guid.Empty))
                _order.Commission = (CommissionEntity)com_commission.SelectedItem;

            _order.Car.Items.Clear();
            
            for (int i = 1; i <= 10; i++)
            {
                Car uc_car = (Car)tab_cars.Controls.Find("uc_car" + i.ToString(), true)[0];
                CarEntity car = uc_car.UnbindCarValues();
                if ((car.CarModel != null) && (car.CarModelID != Guid.Empty) && (CarService.CarHasPickupAndDestinationAddress(car)))
                {
                    _order.Car.Items.Add(car);
                    car.Order = _order;
                }
            }
        }

And where the cars are handled tis is called:

public CarEntity UnbindCarValues()
        {
            //Dispatches is handled while addresses and loadingareas is changed
            if (_car.IsNew)
                _car.CarID = Guid.NewGuid();

            if ((com_carModel.Enabled) && (com_carModel.SelectedItem != null) && (((CarModelEntity)com_carModel.SelectedItem).CarModelID != Guid.Empty))
                _car.CarModel = (CarModelEntity)com_carModel.SelectedItem;
            else
                _car.CarModel = null;
            _car.RegMva = txt_regMva.Text;
            if (chk_extraFeeLarge.Checked)
                _car.CarTypeID = (int)CarType.Large;
            else if (chk_extraFeeSmall.Checked)
                _car.CarTypeID = (int)CarType.Small;
            else
                _car.CarTypeID = null;
            _car.ExpressDelivery = chk_expressDelivery.Checked;
            if ((chk_difrentDestinationAddressOnInvoice.Checked) 
                && (((ComboAddress)com_invoiceDestinationAddress.SelectedItem).Address != null)
                && (((ComboAddress)com_invoiceDestinationAddress.SelectedItem).Address.AddressID != Guid.Empty))
                _car.Address = ((ComboAddress)com_invoiceDestinationAddress.SelectedItem).Address;
            else
                _car.Address = null;
            _car.CommentPublic = txt_commentPublic.Text;
            _car.CommentInternal = txt_commentInternal.Text;

            return _car;
        }
Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 21-Mar-2007 14:52:48   

And where is the Saving code?

Also which LLBLGen Pro runtimeLibrary version are you using?

Noer
User
Posts: 33
Joined: 04-Jan-2007
# Posted on: 21-Mar-2007 14:55:27   

2.0.0.61205

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 21-Mar-2007 15:35:56   

And where is the Saving code? Please post your own code which gives the before mentioned exception.

Noer
User
Posts: 33
Joined: 04-Jan-2007
# Posted on: 21-Mar-2007 15:38:42   

The Button click event:

private void but_saveOrder_Click(object sender, EventArgs e)
        {
            if (ValidateOrder())
            {
                try
                {
                    _order = OrderService.SaveOrder(_order);
                }
                catch (UnableToDeleteDispatchException)
                {
                    MessageBox.Show("Der skedte en fejl, og ordren kunne ikke gemmes.\n Har du forsøgt at fjerne en bil med afsluttede kørsler?", "Fejl", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n" + ex.InnerException + "\n" + ex.InnerException.InnerException, "Fejl", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }
            }
        }

And the Save method

public static OrderEntity SaveOrder(OrderEntity orderToSave)
        {
            if (!orderToSave.IsNew)
            {
                OrderEntity currentOrder = GetOrder(orderToSave.OrderID);

                foreach (CarEntity car in currentOrder.Car)
                {
                    if (!IsCarInOrder(orderToSave, car))
                        CarService.DeleteCar(car);
                }

                foreach (CarEntity car in orderToSave.Car)
                {
                    CarService.SaveCar(car);
                }
            }
            orderToSave.Save(true);
            return GetOrder(orderToSave.OrderID);
        }
Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 21-Mar-2007 16:05:17   

What's the purpose of this loop: foreach (CarEntity car in orderToSave.Car) { CarService.SaveCar(car); }

Cars should be saved when you save the order, since you are passing true for recursive save. Please comment the above for loop and try again. Thanks.

Noer
User
Posts: 33
Joined: 04-Jan-2007
# Posted on: 21-Mar-2007 16:05:28   

I forgot the SaveCar, here it is:

public static void SaveCar(CarEntity carToSave)
        {
            if (carToSave.IsNew)
                carToSave.Save(true);
            else
            {
                CarEntity currentCar = new CarEntity(carToSave.CarID);

                foreach (CarProductEntity cpe in currentCar.CarProduct)
                {
                    if (!IsProductAssociatedToCar(cpe, carToSave))
                    {
                        CarEntity car = new CarEntity(cpe.Car.CarID);
                        ProductEntity product = new ProductEntity(cpe.Product.ProductID);
                        car.CarProduct.Remove(cpe);
                        product.CarProduct.Remove(cpe);
                        cpe.Delete();
                    }
                }

                foreach (DispatchEntity de in currentCar.Dispatch)
                {
                    if ((!IsDispatchAssociatedToCar(de, carToSave)) && (!de.CompletedDate.HasValue))
                    {
                        if (de.DispatchListID.HasValue)
                        {
                            DispatchListEntity dispatchList = new DispatchListEntity(de.DispatchListID.Value);
                            dispatchList.Dispatch.Remove(de);
                        }
                        CarEntity car = new CarEntity(currentCar.CarID);
                        car.Dispatch.Remove(de);
                        de.Delete();
                    }
                }
            }
        }
Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 21-Mar-2007 16:09:32   

If you are handling the recursive saves manually then don't pass true to the order.Save() method.

Also would you please debug your application and tell me at which line of code does it throw the exception.

Noer
User
Posts: 33
Joined: 04-Jan-2007
# Posted on: 21-Mar-2007 16:22:23   

this line fails: carToSave.Save(true); (public static void SaveCar(CarEntity carToSave))

Noer
User
Posts: 33
Joined: 04-Jan-2007
# Posted on: 21-Mar-2007 18:13:04   

I found and solved the problem. In UnbindCarValuesForCarCopy() line 5 should be "carCopy.CarModel = new CarModelEntity(((CarModelEntity)com_carModel.SelectedItem).CarModelID);"

This way it's not a reference to (CarModelEntity)com_carModel.SelectedItem of the car we are copying from.