none
DeleteOnSubmit error RRS feed

  • Question

  • Hello,

    I'm working on a Windows phone application (7.1.1). I have two tables: Main and Vendors.

    Main table
    MainID (PK)
    Name
    Address
    ...


    Vendors table
    VendorID (PK)
    MainID (FK)
    VendorCode
    ...


    There is a 1-to-many relationship between the table Main and the table Vendors. The association is made so that when a Main table item is deleted, all the Vendors table items with that same MainID are deleted. It works, I've checked it.

    The items from the Vendors table are displayed in a ListBox control (binding).

    I can add records to the Vendors table. When I delete a Main table item, it deletes all the corresponding Vendors with the same MainID.

    The problem occurs when I try to delete a vendor by clicking on a button.

    Dim button = TryCast(sender, Button)
    
    If button IsNot Nothing Then
         Using DB As New DemoAppContext.DemoAppContext("Data Source=isostore:/AppDataBase.sdf")
    
              Dim RecordToDelete As Vendor = TryCast(button.DataContext, Vendor)
    
              VendorRecords.Remove(RecordToDelete)
    
              ' This is where I get the error: "Cannot remove an entity that has not been attached."
              DB.VendorRecords.DeleteOnSubmit(RecordToDelete)
    
              DB.SubmitChanges()
    
         End Using
    End If

    I've tried adding the following line:

    DB.VendorRecords.Attach(RecordToDelete)

    before the line that is giving me an error but I get another error:

    An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext.  This is not supported.

    I'm using Visual Basic .NET 2010.

    Thank you!


    Thursday, May 31, 2012 5:26 PM

Answers

  • Hi,

    You try to update an entity that has been loaded using another context (that is exactly what the second error message tells). A simple solution could be to have an underlying DemoAppContext that has the same lifetime than the UI DataContext. See http://msdn.microsoft.com/en-us/gg241309.aspx


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".

    • Marked as answer by milo1981 Friday, June 1, 2012 6:01 PM
    Thursday, May 31, 2012 5:44 PM

All replies

  • Hi,

    You try to update an entity that has been loaded using another context (that is exactly what the second error message tells). A simple solution could be to have an underlying DemoAppContext that has the same lifetime than the UI DataContext. See http://msdn.microsoft.com/en-us/gg241309.aspx


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".

    • Marked as answer by milo1981 Friday, June 1, 2012 6:01 PM
    Thursday, May 31, 2012 5:44 PM
  • Thank you, Patrice, for your answer.

    I'm just starting Windows Phone development, I've seen a few samples but it looks like I'm still missing somethings.

    I've watched the clip in your post and it moves kinda fast through the MVVM. In which part of the clip it says about the DataContext?

    I'm also using the MVVM. I have all the tables, columns and table relationships in a DataContext (Model part).

    Question: In the ViewModel part, do I have to have a Public Class, with an ObservableCollection and database operations (add, remove, update), for every table in database?

    • Marked as answer by milo1981 Friday, June 1, 2012 6:00 PM
    • Unmarked as answer by milo1981 Friday, June 1, 2012 6:00 PM
    Thursday, May 31, 2012 8:34 PM
  • On 5/31/2012 4:34 PM, milo1981 wrote:
    > Thank you, Patrice, for your answer.
    >
    > I'm just starting Windows Phone development, I've seen a few samples but
    > it looks like I'm still missing somethings.
    >
    > I've watched the clip in your post and it moves kinda fast through the
    > MVVM. In which part of the clip it says about the DataContext?
    >
    > I'm also using the MVVM. I have all the tables, columns and table
    > relationships in a DataContext (Model part).
    >
    > Question: In the ViewModel part, do I have to have a Public Class, with
    > an ObservableCollection and database operations (add, remove, update),
    > for every table in database?
     
    Maybe and maybe not it all depends on what you are doing in the ViewModel
     
    Here is a ViewModel that's being used by a WPF demo.
     
    The ViewModel communicates with a Service layer for CRUD operations with
    the EF model
     
    WPF
    MVVM
    Service Layer
    WCF Web service
    BLL
    DAL
    The EF Model.
     using System;
    using System.Collections.ObjectModel;
    using System.Windows.Input;
    using DemoWPFApp.Properties;
    using Services.IServices;
    using BLL.DTO;
     
    namespace DemoWPFApp.ViewModel
    {
        public class PayRollViewModel : WorkspaceViewModel
        {
            private readonly IService1 mService;
            private string __payrollid;
            private string _salary;
            private DTOPayroll _dtopayroll;
            private RelayCommand _updateCommand;
            private RelayCommand _addCommand;
            private RelayCommand _deleteCommand;
             private ObservableCollection<DTOAuthor> _authors = new
    ObservableCollection<DTOAuthor>();
             public PayRollViewModel(IService1 theService)
            {
                mService = theService;
                base.DisplayName = Strings.PayRollViewModel_DisplayName;
                LoadPayRoll();
            }
             public ObservableCollection<DTOAuthor> Authors
            {
                get { return _authors; }
            }
             public string PayRollID
            {
                get { return __payrollid; }
                set
                {
                    __payrollid = value;
                    base.OnPropertyChanged("PayRollID");
                }
            }
             public string Salary
            {
                get { return _salary; }
                set
                {
                    _salary = value;
                    base.OnPropertyChanged("Salary");
                }
            }
             public override string DisplayName
            {
                get
                {
                    {
                        return Strings.PayRollViewModel_DisplayName;
                    }
                }
            }
             DTOAuthor _selectedAuthor;
            public DTOAuthor SelectedAuthor
            {
                get
                {
                    return _selectedAuthor;
                }
                set
                {
                    _selectedAuthor = value;
                    base.OnPropertyChanged("SelectedAuthor");
                    _dtopayroll =  GetPayRollByAuthorID(value.AuthorID);
                    _dtopayroll.AuthorID = value.AuthorID;
                }
            }
             public ICommand UpdateCommand
            {
                get
                {
                    if (_updateCommand == null)
                    {
                        _updateCommand = new RelayCommand(
                            param => Update(),
                            param => CanUpdate
                            );
                    }
                     return _updateCommand;
                }
            }
             public ICommand AddCommand
            {
                get
                {
                    if (_addCommand == null)
                    {
                        _addCommand = new RelayCommand(
                            param => Add(),
                            param => CanAdd
                            );
                    }
                    return _addCommand;
                }
            }
             public ICommand DeleteCommand
            {
                get
                {
                    if (_deleteCommand == null)
                    {
                        _deleteCommand = new RelayCommand(
                            param => Delete(),
                            param => CanDelete
                            );
                    }
                    return _deleteCommand;
                }
            }
             private void Update()
            {
                 if (_dtopayroll !=null)
                {
                    if (_dtopayroll.PayRollID > 0
                    &&  Salary != string.Empty)
                    {
                        _dtopayroll.Salary = Convert.ToInt32(Salary);
                        mService.UpdatePayRollSalary(_dtopayroll);
                    }
                }
                 base.OnPropertyChanged("DisplayName");
            }
             private void Add()
            {
                 if (_dtopayroll != null)
                {
                    if (_dtopayroll.PayRollID == 0
                    && Salary != string.Empty)
                    {
                        _dtopayroll.Salary = Convert.ToInt32(Salary);
                        var payroll =  mService.AddPayRoll(_dtopayroll);
                        PayRollID = payroll.PayRollID.ToString();
                    }
                }
                 base.OnPropertyChanged("DisplayName");
            }
             private void Delete()
            {
                 if (_dtopayroll != null)
                {
                    if (_dtopayroll.PayRollID.ToString() == PayRollID)
                    {
                         mService.DeletePayRoll(_dtopayroll);
                        PayRollID = "";
                        Salary = "";
                        _dtopayroll.PayRollID = 0;
                        _dtopayroll.Salary = 0;
                    }
                }
                 base.OnPropertyChanged("DisplayName");
            }
             bool CanUpdate
            {
                get { return true; }
            }
             bool CanAdd
            {
                get { return true; }
            }
             bool CanDelete
            {
                get { return true; }
            }
             public void LoadPayRoll()
            {
                var dtoauthors = mService.GetAuthors();
                 foreach (var dto in dtoauthors)
                {
                    _authors.Add(dto);
                }
            }
             private DTOPayroll GetPayRollByAuthorID(int id)
            {
                var payroll = mService.GetPayRollByAuthorID(id);
                PayRollID = payroll.PayRollID.ToString();
                Salary = payroll.Salary.ToString();
                return payroll;
            }
        }
    }
     
     
    Friday, June 1, 2012 2:31 AM
  • Thank you, darnold924!

    I'm using a MVVM, but I still get the same error!

    Friday, June 1, 2012 4:49 PM
  • On 6/1/2012 12:49 PM, milo1981 wrote:
    > Thank you, darnold924!
    >
    > I'm using a MVVM, but I still get the same error!
    >
     
    I suggest that you get the record you are about to delete by its ID and
    then delete it with doing it all within the same context. Read it (get
    it in context) from the database and delete it.
     
    The second thing is that you should remove any database code out of the
    ViewModel. As you can see in the ViewModel that I am using,  that there
    is no database code in the ViewModel. The ViewModel is calling the
    Service Layer that leads to the call to the DataAccess Layer that does
    all CURD (create, read, update and delete) operations with the EF model.
     
    Friday, June 1, 2012 7:35 PM