none
Non updateable view error: Unable to update the EntitySet RRS feed

  • Question

  • This question is cross posted on SO: link

    I am getting the following error in my WinForms app.

    Unable to update the EntitySet 'VW_MyView' because it has a DefiningQuery and no <DeleteFunction> element exists in the <ModificationFunctionMapping> element to support the current operation.

    There are a lot of questions about this topic, most seem to be resolved by adding a Primary Key to some table in the database and refreshing the model.

    However, my error pops up for a view that is not update-able and for which I have no intentions of updating. The view is simply a read only EF Entity that I use to populate a read only datagridview.

    The Datagridview.Datasource is bound to a BindingList<VW_MyView>, but there are no direct inserts, updates, or deletes on the view. Furthermore, the error shows up inconsistently. I have two other objects, lets say Parent and Child and when I delete Parent directly there is no error. But if I delete a Child and then try to delete the Parent this error on the VW_MyView is raised. I do expect the view to reflect changes based on updates to Parent and Child, but I am not doing any updates directly to the view.

    I am using Model-View-Presenter pattern, and I am passing a context to the Presenter via dependency injection. As of right now, the Context is not refreshed or disposed throughout the application, until shutdown or critical error state.

    Based on this info, would you expect the error to be raised because I have not implemented the "Modification Function Mapping" (per this answer) or is their perhaps something else going on? Have you encountered similar issues with your views in EF?

    This is the code that raises an exception

    Parent parnt;
    
    parnt = _Parents.Where(p => p.ParentId == _View.ParentId).First();
    
    _Context.Parents.Remove(parnt);
    
    try
    {
        _Context.SaveChanges(); //<-- Error. Sometimes.
    }catch(Exception ex){...


    Tuesday, June 23, 2015 7:20 PM

All replies

  • Hi mantooth29,

    As you could not update or delete the data by the View. I suggest you could bind your DataGridView.DataSource to the Datatable instead of the View. 

    And the link mentioned, the error is often caused by the missing of the primary key. You could check if you have the primary key in your parent and child table.

    And as we don't know what is the structure of your parent and child table and the 'VW_MyView'  view.  we can't reproduce your issue in our machine.  I suggest you could share your project without your confidential information. we could know how you bind the DataSource, and the structure of your database and then help you better.

    Regards,
    Youjun Tang


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, June 25, 2015 9:29 AM
  • Thanks Youjun

    I'll try to separate out some code that could be helpful.

    All of my tables have auto number primary keys.

    As to my bindings, I think this could be my major pain point.

    Here are some relevant details:

    • using Lazy Loading
    • bind with a BindingSource as Object from database.
    • using presenters (MVP) that expose BindingLists of these objects to populate datagridviews and textboxes
    • injecting context into presenters (dont have an IoC container) but am thinking of changing to each presenter making context in its constructor and having them implement IDisposable.

    Here is the presenter that causes issue.

        public class ProcedurePresenter
        {
            private readonly IProcedureView _View;
    
            private MyEntities _Context;
    
            private BindingList<Procedure> _Procedures; //Binds to DataGridView. "Parent" class
            public BindingList<Procedure> Procedures { get { return _Procedures; } }
    
            private BindingList<VW_ProcedureCommandSummaryGUI> _ProcedureCommandSummary; //Binds to DataGridView. View is a summary of "Child" class Commands and other elements. It is intended to be read only
            public BindingList<VW_ProcedureCommandSummaryGUI> ProcedureCommandSummary { get { return _ProcedureCommandSummary; } }
    
            private BindingSource _ProcedureBindingSource;
            
            private bool _IsNew = true;
    
            public ProcedurePresenter(IProcedureView View, MyEntities Context, BindingSource ProcedureBindingSource)
            {
                this._View = View;
    			
    			this._Context = Context;
    
                this._ProcedureBindingSource = ProcedureBindingSource;
    
                Initialize();
            }
    		
            public void Cancel()
            {
                _View.ProcedureIsDirty = false;
    
                if (_IsNew)
                {
                    _ProcedureBindingSource.CancelEdit();
                }
                else
                {
                    if (_ProcedureBindingSource.Current != null)
                    {
                        _Context.Entry(_ProcedureBindingSource.Current as Procedure).Reload();
    
                        _ProcedureBindingSource.ResetBindings(false);
                    }
                }
            }
    
            private void Initialize()
            {
                _Context.Procedures.Load();
    
                _Procedures = _Context.Procedures.Local.ToBindingList();
    
                _View.SaveProcedure += Save;
    
                _View.NewProcedure += New;
    
                _View.LoadProcedure += Load;
    
                _View.DeleteProcedure += Delete;
    
                _View.ProcedureStatusChange = "Ready";
    
                Fetch_Procedure_Command_Summary(_Procedures.First());
            }
    
            private void Save()
            {
                Procedure proc = this._ProcedureBindingSource.Current as Procedure;
    
                Fetch_Procedure_Command_Summary(proc);
    			
                proc.ProcedureId = _View.ProcedureId;
    
                proc.ProcedureName = _View.ProcedureName;
    
                proc.LastModified = DateTime.Now;
    
                if (this._IsNew)
                {
                    this._ProcedureBindingSource.EndEdit();
                }
    
                try
                {
                    _Context.SaveChanges();
    
                    this._IsNew = false;
    
                    _View.ProcedureStatusChange = "Procedure Saved";
                }
                catch (System.Data.Entity.Infrastructure.DbUpdateException ex)
                {
                    Exception innerException = ex.InnerException;
    
                    while (innerException != null)
                    {
                        if (innerException.InnerException != null)
                        {
                            innerException = innerException.InnerException;
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (innerException != null && innerException.Message.Contains("UNIQUE constraint"))
                    {
                        _View.ProcedureStatusChange = "Error: Tried to create a Procedure Name that already exists. Please change the name " +
                                        "so that it is unique.";
                    }
                    else if (innerException != null)
                    {
                        _View.ProcedureStatusChange = "Error: " + innerException.Message;
                    }
                    else
                    {
                        _View.ProcedureStatusChange = "Error: " + ex.Message;
                    }
                }
                catch (Exception ex)
                {
                    if(this._IsNew)
                    {
                        _Procedures.Remove(proc);
                    }
                    else
                    {
                        _Context.Entry(proc).CurrentValues.SetValues(_Context.Entry(proc).OriginalValues);
                    }
    
                    string msg = (ex.InnerException != null) ? ex.InnerException.Message : ex.Message;
    
                    _View.ProcedureStatusChange = "Error Saving: " + msg;
                }
    
                _View.ProcedureIsDirty = false; 
            }
    
            private void New() 
            {
                New_Procedure();
            }
    
            private void Load()
            {
                Load_Procedure(_View.ProcedureId);
            }
    
            private void Delete()
            {
                Procedure proc;
    
                if (!this._IsNew && _View.ProcedureId != 0)
                {
                    proc = _Procedures.Where(p => p.ProcedureId == _View.ProcedureId).First();
    
                    _Context.Procedures.Remove(proc);
                    try
                    {
                        _Context.SaveChanges(); //Errors here. Sometimes.
    
                        _View.ProcedureStatusChange = "Procedure Deleted";
                    }
                    catch (Exception ex) 
                    {
    					_View.ProcedureStatusChange = "Error Deleting: " + ex.Message;
                    }
    
                    _View.ProcedureIsDirty = false; 
                }
                else
                {
                    Cancel();
                }
            }
    
            private void New_Procedure()
            {
                Blank_Procedure();
    
                this._IsNew = true;
    
                _View.ProcedureIsDirty = true;
    
                _View.ProcedureStatusChange = "New Procedure";
    
                Fetch_Procedure_Command_Summary(new Procedure() { ProcedureId = 0 });
            }
    
            private void Blank_Procedure()
            {
                _View.ProcedureId = 0;
                
                _View.ProcedureName = string.Empty;
    
                _View.ProcedureLastModified = null;
    
                _ProcedureCommandSummary = null;
            }
    
            private void Load_Procedure(int ProcedureId)
            {
                if (ProcedureId != 0)
                {
                    try
                    {
                        Procedure proc = _Context.Procedures.Where(p => p.ProcedureId == ProcedureId).First();
    
                        Load_Procedure(proc);
                    }
                    catch (Exception ex)
                    {
                        _View.ProcedureStatusChange = "Error: Unable to find Procedure with this Id";
                    }
                }
            }
    
            private void Load_Procedure(Procedure Proc)
            {
                _View.ProcedureId = Proc.ProcedureId;
    
                _View.ProcedureName = Proc.ProcedureName;
    
                _View.ProcedureLastModified = Proc.LastModified;
    
                this._IsNew = false;
    
                Fetch_Procedure_Command_Summary(Proc);
            }
    
            private void Fetch_Procedure_Command_Summary(Procedure Proc)
            {
                _Context.Set<VW_ProcedureCommandSummaryGUI>()
                        .Local.ToList()
                        .ForEach(x =>
                        {
                            _Context.Entry(x).State = EntityState.Detached;
                            x = null;
                        }); //Doing this to clear the view and getting updated results below
    
                this._Context.VW_ProcedureCommandSummaryGUI.Where(vw => vw.ProcedureId == Proc.ProcedureId)
                        .OrderBy(vw => vw.ForcedSequence)
                        .ThenBy(vw => vw.Sequence).Load();
    
                _ProcedureCommandSummary = _Context.VW_ProcedureCommandSummaryGUI.Local.ToBindingList();
            }
        }


    • Edited by mantooth29 Friday, June 26, 2015 2:22 PM
    Friday, June 26, 2015 2:21 PM
  • Hi,

    You can't operate the database by View. You could use the DataTable which bind with dataBase.

    And It's hard to reproduce your issue with the code.

    Could you upload the whole project to OneDrive or others, It can help to reproduce the issue.

    Friday, July 3, 2015 7:24 AM