views:

805

answers:

3

Hi, in my data layer class I have created a function to manually refresh the data source.

Public Sub DiscardAllChanges()

    _Context.Refresh(RefreshMode.OverwriteCurrentValues)

End Sub

The problem is that the context ChangeSet after this operation still trace the previous operation of Insertion, Deletion and Update that I made calling manually InsertOnSubmit, etc.

Is it possible to clear also the ChangeSet in some way? Or if not can you suggest me another solution? Do I have to create a ChangeSet layer in the Business?

A: 

Sounds like your trying to deal with concurrency issues? This is where when you submit, the database has already changed which causes your submit to fail. Let me know if this is what your after:

DataClasses1DataContext dc = new DataClasses1DataContext();
try
{
    dc.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict);
}
catch (System.Data.Linq.ChangeConflictException ex)
{
    foreach (var conflict in dc.ChangeConflicts)
    {
        conflict.Resolve(System.Data.Linq.RefreshMode.KeepChanges);
    }
    dc.SubmitChanges();
}

This pattern does the heavy lifting for you on concurrency issues. The RefreshMode has overloads to either force your change in, refresh the latest values EXCEPT your change, or let the database overwrite your changes. You can then submit again. Note that committing in full is a recursive process, your subsequent call to submit changes can also fail.

Spence
probably I explained it not well (sorry for my english :)). I call the InsertOnSubmit or DeleteOnSubmit to preapare the data to be changed, but before effectively calling the SubmitChanges I dedice to discard all. So I Refresh the data, but the ChangeSet still contains tracks to the previous ops.
marco.ragogna
+4  A: 

The easiest way to handle this is to treat the DataContext as your unit of work. Perform an atomic set of related operations on a single DataContext, then after either success or failure, Dispose() it (ideally via using) and throw it away.

Start you next set of operations on a new DataContext. Likewise, you can re-query for data.

On an object-by-object basis, you can use GetOriginalEntityState (on the table) to get the original values, but you'd need to re-apply to a "live" object, and this doesn't handle the delete/insert cases.

Marc Gravell
Do you mean that I have to call InsertOnsumbit, or DeleteOnSubmit only when I am really sure I want to perform that operations on the DB? Practically I always need to call SubmitChanges after those?
marco.ragogna
Well, I'm pretty sure that you can cancel an "InsertOnsumbit" with a "DeleteOnSubmit" (and nothing actually goes to the db); I haven't tried cancelling a "DeleteOnSubmit"...
Marc Gravell
Is the ChageSet object immutable or are there any tricks to reset it?
marco.ragogna
As I understand it, the ChangeSet is the result of querying the objects at a point in time; once you have called GetChangeSet it doesn't get updates or impact the original object in any way. You would have to enumerate the changes manually. Or just start a fresh `DataContext`.
Marc Gravell
Verified: here is the end of GetChangeSet: "return new ChangeSet(list.AsReadOnly(), list2.AsReadOnly(), list3.AsReadOnly());" - so this is indeed immutable.
Marc Gravell
Thank you for the support Mark, in the end I think I will start a fresh DataContext as you suggested. Bye ;)
marco.ragogna
A: 

dc.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, item);

john