views:

2797

answers:

4

I have a update method in my data layer such this:

public clacc datalayerSec_User
private objUIData as new UIData
Public Function Update(ByVal objUser As SEC_USER) As Boolean
  Try
    objUIData.SEC_USERs.Attach(objUser)
    objUIData.Refresh(RefreshMode.KeepCurrentValues, objUser)
    objUIData.SubmitChanges(ConflictMode.ContinueOnConflict)
    Return True
  Catch ex As Exception
    Throw ex
  End Try
End Function
end class

And I write this code to update my data:

Dim tmpUser As New UI_Class.BAL.Security.cls_SEC_USER
Dim tblUser = tmpUser.GetAll.SingleOrDefault(Function(x) x.DS_OPENID = pOpenID)
tblUser.DT_LAST_LOGIN = DateTime.Now
tmpUser.Update(tblUser)

When I run it, I have this error message: Cannot attach an entity that already exists.

How can it be fixed?

+2  A: 

If the DataContext that you retrieved the user object from hasn't been disconnected or disposed, I don't think need to call Attach(). What is the lifecycle of objUIData?

Zachary Yates
This error happens when trying to attach an object created from one DataContext to another, too.
leppie
I put objUIData now ;)
mavera
As long as datalayerSec_User is still around, you won't have to do any attaching. The updates will happen if you have change tracking enabled (by default I think) and all you have to do is call submit changes.
Zachary Yates
A: 

I dont know the answer to you question, and I have been stuck with the same issue too, but I adopted a simple strategy to prevent these little issues.

Instead of trying to attach/detach, fetch the actual object as soon as possible; this works quite well in web scenario's.

leppie
A: 

aren't teher Any ideas about this subject? I couldn't solve this problem yet.

mavera
+3  A: 

The easiest way to get around this issue is to use the same DataContext when retrieving the user object and updating.

In general, a DataContext should be kept alive for a "unit of work", in other words, you use it to retrieve whatever object you want to change, then change its properties, and then just do SubmitChanges() on the DataContext. No need to reattach the entity to the DataContext, since it already has a reference to it.

My VB skills are none existing, but something like this should work (note: very crude pseudo code coming up, things like properly disposing of the DataContext is recommended):

class cls_SEC_USER
{
 private _UIData = new UIData();

 public User SingleOrDefault(int x)
 {
  return _UIData.Users.SingleOrDefault(y => y.UserId == x);
 }

 public void Update(User u)
 {
  _UIData.SubmitChanges();
 }
}

// ..........

cls_SEC_USER tmpUser = new cls_SEC_USER(); 
User u = tmpUser.SingleOrDefault(4);

if(u != null)
{
 u.DT_LAST_LOGIN = DateTime.Now;
 tmpUser.Update(u);
}

Brian Orrell has a pretty good run-down of the issues that you are experiencing, if you want to dig in deeper.

Egil Hansen