Error:An entity object cannot be referenced by multiple instances of IEntityChangeTracker

.net c# entity-framework entity-framework-6

Accepted Answer

I discovered two answers:

The first was to cast nothing and utilise the existing DbContext:

In order to utilise a general DbContext instance or a specialised PHSRP DashboardDataModel depending on the entity state, extra infrastructure is needed.

Although it solves the issue, I don't like it since it doesn't explain or address the root of the issue.

PHSRP_DashboardDataModel _DBC = null;
DbContext _PDBC = null;
Boolean existingContext;

if (GetDbContextFromEntity(ActiveWorkSession)!=null)    // is ActiveWorkSession still attached to a Dbcontext ?
{
    _PDBC = GetDbContextFromEntity(ActiveWorkSession);        //  Get that Context
    existingContext = true;
}
else
{
    _DBC = new PHSRP_DashboardDataModel();             // Open new Context and attach
    _DBC.EmployeeWorkSessions.Attach(ActiveWorkSession);
    existingContext = false;
}

switch (lPunch.Type)
{
     case PunchType.OutForShift:
     {
        // Remove END punch, set SessionEnd time to null 
        try
        {
            WorkEndRecord wsr = ActiveWorkSession.WorkEndRecords.First();

            if (existingContext)
            {
                ActiveWorkSession.WorkEndRecords.Remove(wsr);
                ActiveWorkSession.WorkEndDateTime_Actual = null;
                _PDBC.SaveChanges();
            }
            else
            {
               _DBC.WorkEndRecords.Remove(wsr);
               ActiveWorkSession.WorkEndDateTime_Actual = null;
              _DBC.SaveChanges();
            }

        }
        catch (Exception ex)
        {
             //  handle exception
        }

        tcUser.UpdateClockState();
        UpdateClockView();

        break;
     }

         |
         |
     Other cases
         |
         |
}

After searching for other references to the Database Context in response to Frank Fajardo's query, I eventually found the second, superior approach.

A clock-out is the job that this code is "oeundoing." I discovered my old reference to ActiveWorkSession there, still linked.

In the SessionClockOut method, I did not wrap my reference to the Database context in a "oeusing" block. I included a disconnect command as a test, and it was successful. I then added a "using" block to the _DBC. Because of this, I was able to use my original btn UndoButton Click code without having to separate the ActiveWorkSession object from the Context:

private Boolean SessionClockOut(DateTime timeOUT)
{
    Boolean success = false;
    Boolean abort = false;

    tcPunch newPunch = new tcPunch();

 // Added 'using' statement
    using (PHSRP_DashboardDataModel _DBC = new PHSRP_DashboardDataModel())
    {
        while (!success && !abort)
        {
            var wsUpdate = _DBC.EmployeeWorkSessions
                               .Where(w => (w.EmployeeWorkSessionID == ActiveWorkSession.EmployeeWorkSessionID))
                               .Include(w => w.WorkStartRecords)
                               .Include(w => w.WorkEndRecords)
                               .Include(w => w.WorkSessionBreaks)
                               .FirstOrDefault();

            if (wsUpdate != null)
            {
                WorkEndRecord er = new WorkEndRecord();

                try
                {
                    wsUpdate.WorkEndDateTime_Actual = timeOUT;

                    er.EmployeeWorkSessionID = ActiveWorkSession.EmployeeWorkSessionID;
                    er.EditTimeStamp = DateTime.Now;
                    er.WorkEndDateTime_Official = timeOUT;
                    er.VarianceReasonID = VarianceReason.VR_None;
                    er.EditByID = ActiveWorkSession.EmployeeID;

                    wsUpdate.WorkEndRecords.Add(er);
                    _DBC.SaveChanges();

                    ActiveWorkSession = wsUpdate;
                    tcUser.UpdateClockState();
                        UpdateClockView();

        //  Tried this before adding the using statement. It also worked.
        //          _DBC.Entry(ActiveWorkSession).State = EntityState.Detached;         // Release from DB Context
                    PreviousWorkSession = ActiveWorkSession;                            // needed For Undo Punch 
                    ActiveWorkSession = null;                                           // Worksession has ended
                    success = true;

                }
                catch (DbUpdateException e)
                {
                   //  handle exception...
                    abort = true;
                    throw;
                }

                newPunch.EmployeeID = wsUpdate.EmployeeID;
                newPunch.WorksessionID = wsUpdate.EmployeeWorkSessionID;
                newPunch.Type = PunchType.OutForShift;
                newPunch.TimeStamp = er.EditTimeStamp;
                if (tcUser.hasPriv(PrivilegeTokenValue.TC_UndoRecentPunch)) tcLastPunchUndo.StartUndoTimer(newPunch);
            }  // if
        }  //  while 

    }  // using

    return success;
}

I'm new to Entity Framework, thus I don't fully get all the problems with using the DbContext.

0
12/4/2017 10:31:48 PM

Popular Answer

ZZZ_tmp


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow