Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework (3.5) - Reject Changes

I have this service which is Singleton and Single threaded and serves bunch of low volume clients. It uses Entity Framework and Data in SQL Server.

If any one of the client's request to Save Data fails, all the subsequent requests are being failed as every time it is trying to save the original failed data object.

Is there is any way to Undo changes to EF data when save fails?

Thanks in Advance

like image 593
Bhuvan Avatar asked Aug 18 '10 18:08

Bhuvan


4 Answers

Entity-models / data-contexts / etc are best handled as units of work. If you need to cancel it, simply discard the context and start with a new one. And if you succeed, discard it anyway! Each request should really be using separate data-contexts, otherwise you can get a range of problems:

  • threading (although it sounds you've avoided this by making it single-threaded)
  • data growth (there is an identity manager; every row you touch stays around; multiple times, in fact)
  • general isolation etc
  • connection lifetime management (hogging an open connection)
  • etc
like image 74
Marc Gravell Avatar answered Nov 05 '22 09:11

Marc Gravell


Note: you can upgrade to EF 4.1 or 4.2 which makes this job easy as a charm:

context.Entry(myEntity).State = EntityState.Unchanged;

Please refer to this for detail.

Create a partial class to your ObjectContext generated class, and include the following methods in it (VB, sorry - should be easily transcribed to C#):

Public ReadOnly Property DirtyObjects() As IEnumerable(Of ObjectStateEntry)
  Get
    Return ObjectStateManager.GetObjectStateEntries(
      EntityState.Added Or 
      EntityState.Deleted Or 
      EntityState.Modified)
  End Get
End Property


Public Overloads Sub Refresh()
  For Each entry In DirtyObjects
    Select Case entry.State

      Case EntityState.Modified
        Dim original = entry.OriginalValues
        For Each prop In entry.GetModifiedProperties()
          Dim ordinal = original.GetOrdinal(prop)
          entry.CurrentValues.SetValue(ordinal, original(ordinal))
          RaisePropertyChanged(entry.Entity, prop)
        Next
        entry.AcceptChanges()
      Case EntityState.Deleted
        'I think I would need to call the above again, cuz it might be
        'changed values on a Deleted-state entry too.
        entry.ChangeState(EntityState.Unchanged)
      Case EntityState.Added
        entry.ChangeState(EntityState.Detached)
      Case Else
        'do nothing
        Debug.Fail("It's not supposed to stop here.")
    End Select
  Next
End Sub

Heads up! In the new upcoming version this feature has became hell of a lot easier.

like image 36
Shimmy Weitzhandler Avatar answered Nov 05 '22 08:11

Shimmy Weitzhandler


The Answer to the Question is "You Cannot discard Changes to the Context" instead one has to discard ObjectContext as Marc explained.

like image 34
Bhuvan Avatar answered Nov 05 '22 08:11

Bhuvan


You can refresh the entity by calling

context.Refresh(RefreshMode.StoreWins, entity)

so I see no need for RejectChanges.

like image 39
Sven Avatar answered Nov 05 '22 09:11

Sven