0

Alright...Entity Framework 6 question for all y'alls.

I'm writing a small intranet portal using EF. It's a pretty simple CRUD using a gridview. Everthings to be going swimmingly but I'm having an issue while attempting to save changes.

For the sake of paging, sorting and filtering on the gridview, I create a session variable that holds a list of entity objects then I bind that session variable to the gridview.

//Class level variables
private nsdc_supplyEntities _context = new nsdc_supplyEntities();
private VlanClass _vc;
private EnvironmentTypesClass _ec;

protected void Page_Load(object sender, EventArgs e)
{
    _vc = new VlanClass(_context);
    _ec = new EnvironmentTypesClass(_context);

    if (!IsPostBack)
    {
        Session["vlans"] = _vc.GetAllVlans();
        BindData();
    }
}

protected void BindData()
{
    GridView1.DataSource = Session["vlans"];
    GridView1.DataBind();
}

protected void GridView1_EditVlan(object sender, GridViewEditEventArgs e)
{
    GridView1.EditIndex = e.NewEditIndex;
    BindData();
}

This way, if the user filters the list down to a smaller result set or sorts and pages then does some other event that triggers a postback, the gridview's set remains constant.

But from what I can tell, the list of Vlans in Session["vlans"] no longer has a context (due to a postback event?). So when I try to edit the selected vlan and save it (particularily when I try to add an environment_type child entity to the vlan entity) I get an error.

I've tried reattaching the vlan entry back into _context but that brought up a whole 'nother ball of wax. What is the best way to do this?

Here's my update as it stands:

protected void UpdateVlan(object sender, GridViewUpdateEventArgs e)
{
    CheckBoxList environmenttypesCBL = (GridView1.Rows[e.RowIndex].FindControl("EnvironmenttypesCBL") as CheckBoxList);
    int vlanid = Convert.ToInt32(((Label)GridView1.Rows[e.RowIndex].FindControl("lblid")).Text);

    //At first I was creating a new instance of vlan in question and saving that, 
    //but then database and the Session["vlan"] variable (and gridview) is out of sync
    //vlan editedVlan = new vlan();
    //editedVlan = _vc.GetVlanByID(vlanid);

    //Get the vlan I am editing from Session["vlan"]
    List<vlan> list = Session["vlans"] as List<vlan>;
    vlan editedVlan = list.Find(i => i.id == vlanid);

    //Tried reattaching but "The object cannot be detached because it is not attached to the ObjectStateManager."
    //_context.Attach(editedVlan);

    #region EnvironmentTypes
    editedVlan.environment_type.Clear();
    if (environmenttypesCBL.Items.Count > 0)
    {
        foreach (ListItem l in environmenttypesCBL.Items.Cast<ListItem>())
        {
            //tried adding an environment_type to the editedVlan but "The object cannot be detached because it is not attached to the ObjectStateManager."
            if (l.Selected)
                editedVlan.environment_type.Add(_ec.GetEnvironmentTypeByID(Convert.ToInt32(l.Value)));
        }
    }
    #endregion

    _vc.UpdateSelectedVlan();

    GridView1.EditIndex = -1;
    BindData();
}

1 Answer 1

1

Your _context is created EVERY time you POST or GET, and the list of vlans are bound to a different context as a result.

Session doesn't care about POST or GET, I think you should change this:

_vc = new VlanClass(_context);
_ec = new EnvironmentTypesClass(_context);

if (!IsPostBack)
{
    Session["vlans"] = _vc.GetAllVlans();
    BindData();
}

To this:

if (Session["vlans"] == null )
{
   _context = new nsdc_supplyEntities();  // only create the context here not in the instance var declaration.
   _vc = new VlanClass(_context);
   _ec = new EnvironmentTypesClass(_context);
    Session["vc"] = _vc;
    Session["vlans"] = _vc.GetAllVlans();
    Session["context"] = _context;
}
else
{
    _context = (DbContext)Session["context"];  // cast to your Context
   _vc = (VlanClass) Session["vc"]  ;
}

if (!IsPostBack)
{
    BindData();
}
Sign up to request clarification or add additional context in comments.

3 Comments

That is interesting. This is more elegant that what I was doing. I'm a little confused about the second line of the else. The session variable is a list of vlans. My guess is you're trying to attach it to _vc or something but _vc is just an instance of a class with a bunch of query methods. I would think List<vlan> list = (List<"vlans">)Session["vlans"]; would make more sense but I'm not sure that's what you're getting at.
ah, yes... I screwed that up (will edit). But essentially you are losing your context because you are creating a new one.
Ok, so I posted a couple times on here with issues then realized it those issues were caused by my own stupidity. (so I posted and deleted a few times) However, I'm excited to say, this solution works as advertised and I am very greatful. Thank you TMK.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.