Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection" error?

I have a doubt concerning the Entity Framework in .NET.

I have a simple ASP .NET web page that has to insert some data in SQL Server with this function:

public void InsertSimulation()
{
    icarus_portalEntities entitites = new icarus_portalEntities();

    // Build the Simulation
    T004_SIMULATIONS tSimulation = T004_SIMULATIONS.CreateT004_SIMULATIONS(0, name_, creationDate_, gsoapPort_, endTimeStep_, scenarioX_, scenarioY_, penetrationRates_.wifi, penetrationRates_.gprs, penetrationRates_.wimax, penetrationRates_.lte, penetrationRates_.mcn, penetrationRates_.edge, penetrationRates_.hsdpa, totalNumberOfNodes_, "RandomWalkMobility", ((RandomWalkMobility)mobility_).vehicularSpeed, ((RandomWalkMobility)mobility_).angleVariation, ((RandomWalkMobility)mobility_).cellRadius, ((RandomWalkMobility)mobility_).decorrelation, ((RandomWalkMobility)mobility_).minimumDistance, false);

    // Bind the Simulation with the FK of user
    T001_USERS tUser = entitites.T001_USERS.First(p => p.user_name == createdBy_);
    tUser.T004_SIMULATIONS.Add(tSimulation);

    // Bind the Simulation with the FK of the crmm
    T003_CRRM tCrmm = entitites.T003_CRRM.First(p => p.name == crmm_.Name);
    tCrmm.T004_SIMULATIONS.Add(tSimulation);

    // Add the created sessions to the simulation
    foreach (SimulationSession session in SimulationSession.createdSessions_)
    {
        if (session.GetType() == typeof(WebSession))
        {
            // Build the session and web session
            T008_SESSIONS tWebSession = ((WebSession)session).Insert(entitites);

            // Bind the session to the simulation
            tSimulation.T008_SESSIONS.Add(tWebSession);
        }
    }

    // Add the enanabled technologies to the simulator
    foreach (EnabledTechnologies enabled in enabledTechnologies_)
    {
        // Build the enabled technology
        T005_ENABLED_TECHNOLOGIES tEnabled = T005_ENABLED_TECHNOLOGIES.CreateT005_ENABLED_TECHNOLOGIES(0, enabled.centerX, enabled.centerY, enabled.radius, false);

        // Bind the enabled technolgy with the simulator
        T002_SIMULATORS tSimulator = entitites.T002_SIMULATORS.First(p => p.id == enabled.simulatorId);
        tSimulator.T005_ENABLED_TECHNOLOGIES.Add(tEnabled);

        // Bind the enabled technolgoy with the simulation
        tSimulation.T005_ENABLED_TECHNOLOGIES.Add(tEnabled);
    }

    entitites.SaveChanges();
}

The thing is that when the code tries the sentence:

// Bind the enabled technolgy with the simulator
T002_SIMULATORS tSimulator = entitites.T002_SIMULATORS.First(p => p.id == enabled.simulatorId);

It gives me the error:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

I found, with other related questions, that somehow the connection of the Entity object (entities) is closed when it is passed to the method in the statement:

// Build the session and web session
T008_SESSIONS tWebSession = ((WebSession)session).Insert(entitites);

The Insert function is implemented as:

public T008_SESSIONS Insert(icarus_portalEntities entities)
{
    // Create new session object with data
    T008_SESSIONS tSession = T008_SESSIONS.CreateT008_SESSIONS(0, name_, periodicty_, false);
    using (entities)
    {
        // Create new web session object with data
        T010_SESSIONS_WEB tSessionWeb = T010_SESSIONS_WEB.CreateT010_SESSIONS_WEB(0, (int)lambda_, (int)pagesPerSession_, (int)objectsSize_.alpha, (int)objectsSize_.beta, (int)objectsPerWebPage_.alpha, (int)objectsPerWebPage_.beta, (int)timeBetweenPages_.alpha, (int)timeBetweenPages_.beta, (int)timeBetweenObjects_.alpha, (int)timeBetweenObjects_.beta, false);

        // Add to the session the web session (bind FK)
        tSession.T010_SESSIONS_WEB.Add(tSessionWeb);

        // Add session to the rest of the entities
        entities.AddToT008_SESSIONS(tSession);

        // Commit all the data to the database
        entities.SaveChanges();

        //var tempSession = entities.T008_SESSIONS.First(n => n.Equals(tSession.id));
        //tempSession.T010_SESSIONS_WEB.Add(tSessionWeb);
    }
    return tSession;        
}

The good news is that the code that Insert function encapsulates I can move it to the place which is called. So my question is: What if there is a place in which I would be forced to call the function? How then I could avoid the error. Passing the parameter as reference (I tried and did not work)

Thank you very much in advance!

Julen.

like image 697
Julen Avatar asked Dec 16 '22 15:12

Julen


2 Answers

What if there is a place in which I would be forced to call the function? How then I could avoid the error. Passing the parameter as reference (I tried and did not work)

The problem is in your Insert() function you are wrapping entities in a using(){} statement.

using (entities) //calls dispose
{
} 

When the using finishes it is calling dispose on your entities and closing your connection.

Your context should remain active for the lifetime of our unit of work. Ideally your using statement should be in InsertSimulation() as from the code it appears that is your unit of work for you entitites.

like image 114
Mark Coleman Avatar answered Dec 21 '22 23:12

Mark Coleman


If you look at the method public T008_SESSIONS Insert(icarus_portalEntities entities)

you are passing a reference of your entities object and because it is using a using statement

using (entities) {}

it will dispose the object

like image 39
TBohnen.jnr Avatar answered Dec 22 '22 00:12

TBohnen.jnr