I just had this error where entity framework was complaining about my object already being referenced by the data context that I originally got the object from. In LINQ to SQL I guess this was just taken care of for me. I would get the object in a using statement so that the data context was cleared when I was through with the context. Then I could do what ever I wanted to with the object after that – to include throwing it back to the database.
I came across the fix to this issue here: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/501d7b99-0cb9-44b6-b2cd-16275a151b31 which simply suggests detaching the object from the original context before I kill that context. Then I can re-attach the object to a new context later on. This solved the issue…but uncovered more issues.
Here is my post to the MS forum:
-----------------------------------------------------------------------------------
Working in a web app I am very fond of the Repository approach. I generally create a new context inside a using statement which then kills the context for me once my snippet of work is complete. So for an AccountsRepository I might have a Save(Account account) method which would have something like the following:
using (RanchBuddyDataContext dc = new Connection().GetContext())
{
if(account.AccountID > 0)
{
dc.Accounts.Attach(account, true);
}
else
{
dc.Accounts.InsertOnSubmit(account);
}
dc.SaveChanges();
}
While this worked great in LINQ to SQL I am finding that it doesn't work so well with the Entity Framework. I am now getting the error that started this thread. In order to address this problem I have to do a few things and am not liking the work that goes into this. Hopefully someone can adjust my way of thinking on this.
For my particular issue I have a person that logs into the system. Once the log in is correct I stash their account object (fairly light) into their current session. I then refer to that now and then as needed. This works great. However, when the user goes to the edit account screen, I would normally load the screen with their session held Account object. Allow the user to edit their data and then throw it at a repository method as descibed above.
Not any more!
Up to the point where the user logs in is unchanged. However, the object that is returned to me by my login method now has to be detached from the context - a step that I must remember any time that I want to keep and object out of the db, fiddle with it (edit it), and then eventually persist it back to the db. Then it is put in the session for later use. Once the user edits their account I have to get an original copy of the object (I am guessing so that the context is aware of it???) and then attempt to persist my object (with changes) back to the db.
I now have this code for getting the Account by username:
public Account GetAccountByUsername(string Username)
{
Account result = null;
using (RanchBuddyEntities dc = connection.GetContext())
{
result = dc.AccountSet.Where(a => a.Username == Username).FirstOrDefault();
dc.Detach(result);
}
return result;
}
If the account that is returned from a username search matches the supplied password then the account object here goes into my session. Notice that at the bottom of my query above I have a dc.Detach(result) statement to remove it from the context. From what I have read so far I have to do this so that I can re-attach it later on or keep a copy of the original object with me everywhere I go.
Then comes my save code.
using (RanchBuddyEntities dc = connection.GetContext())
{
if(account.AccountID > 0)
{
Account original = dc.AccountSet.Where(a => a.AccountID == account.AccountID).FirstOrDefault();
dc.ApplyPropertyChanges("AccountSet",account);
}
else
{
dc.AddToAccountSet(account);
}
dc.SaveChanges();
}
In this code I now have to get the original object into the context (as I don't carry the original object around with me just in case I need it and I guess the context is not aware of it if I don't manually load it??), then ApplyPropertyChanges of my updated object, and finally SaveChanges() on the context.
I would love to hear if anyone has a better way of working with this. I much prefer the way I was able to do this in LINQ to SQL as there were less steps to remember and I didn't need to litter various methods with snippets so that one method would work correctly with another (when they shouldn't care about each other at all).
-----------------------------------------------------------------------------------
I would love to hear of a better solution to this problem that shouldn’t be a problem.