So, I am just about at my wits end here. I am an experienced programmer and SQL user but new to Entity Framework. (Using VS Pro 2015, EF 6)
This is my first post here, forgive me if I don't have all the protocols down yet.
I am getting the error “An entity object cannot be referenced by multiple instances of IEntityChangeTracker” when trying to attach an entity object to a Database context. I understand what the error means: My object is already attached to a context. What I don’t understand is why/how my object is still attached to a database context.
The object in question is fetched via a method call on an owning object:
ActiveWorkSession = tcUser.getActiveWorkSession();
Here is the getActiveWorkSession method:
public EmployeeWorkSession getActiveWorkSession()
{
EmployeeWorkSession activeWS = null;
using (PHSRP_DashboardDataModel _DBC = new PHSRP_DashboardDataModel())
{
var ews = _DBC.EmployeeWorkSessions
.Where(w => (w.EmployeeID == this.EmployeeRecord.EmployeeID) &&
(w.WorkEndDateTime_Actual == null))
.Include(w => w.WorkStartRecords)
.Include(w => w.WorkEndRecords)
.Include(w => w.WorkSessionBreaks);
if (ews.Count() > 0)
{
activeWS = ews.First();
if (ews.Count() > 1)
{
activeWS = ews.Last();
}
}
}
return activeWS;
}
You see that, in addition to being a local scope object, the DbContext (_DBC) is disposed of by the using statement before the method returns. So when later, I need to attach this ActveWorkSession to a DbContext again (since I disposed of its original context!) I first tried this:
private void btn_UndoButton_Click(object sender, EventArgs e)
{
|
|
// Various condition tests
|
|
tcPunch lPunch = tcLastPunchUndo.LastPunch;
PHSRP_DashboardDataModel _DBC = new PHSRP_DashboardDataModel();
_DBC.EmployeeWorkSessions.Attach(ActiveWorkSession);
// Blows up here ^
switch (lPunch.Type)
{
Cases with try-catch
}
}
This gives me the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker" at the Attach statement.
Since apparently, in some cases, I was still attached to a DbContext I decided to use that context:
private void btn_UndoButton_Click(object sender, EventArgs e)
{
|
|
// Various condition tests
|
|
tcPunch lPunch = tcLastPunchUndo.LastPunch;
PHSRP_DashboardDataModel _DBC;
if (GetDbContextFromEntity(ActiveWorkSession)!=null) // is ActiveWorkSession still attached to a Dbcontext ?
{
_DBC = (PHSRP_DashboardDataModel) GetDbContextFromEntity(ActiveWorkSession); // Get that Context
// Blows up here ^
}
else
{
_DBC = new PHSRP_DashboardDataModel(); // Open new context and attach
_DBC.EmployeeWorkSessions.Attach(ActiveWorkSession);
}
switch (lPunch.Type)
{
// Cases with try-catch
}
}
The GetDbContextFromEntity code is from a StackOverflow answer
This of course gives me an InvaildCastException: "Unable to cast object of type 'System.Data.Entity.DbContext' to type 'PHSRP_Dashboard.PHSRP_DashboardDataModel'." when I attempt to cast the base type of DbContext to my derived type of PHSRP_DashboardDataModel. I’m aware that that was wishful thinking on my part.
So I am looking for a solution. I’m flexible. A way to disconnect the ActiveWorkSession from its existing dbcontext, or a way to get a proper handle on that existing context, or some other option I haven’t seen yet.
My thanks.
Modifying my query (as suggested by Frank) to:
var ews = _DBC.EmployeeWorkSessions
.Where(w => (w.EmployeeID == this.EmployeeRecord.EmployeeID) &&
(w.WorkEndDateTime_Actual == null))
.Include(w => w.WorkStartRecords)
.Include(w => w.WorkEndRecords)
.Include(w => w.WorkSessionBreaks)
.AsNoTracking();
did not resolve the problem- Same error