c# - EF6 Transaction rollback & concurrency issue -


once rollback transaction , try again, fails dbupdateconcurrencyexception.

after looking @ sql profiler, see first time insert query sent, expected, while second time tries update, though first 1 rolled back?!

first query:

exec sp_executesql n'insert [dbo].[fiscalreceipt]([purchasetime], [receiptnumber], [cash], [card], [bank]) values (@0, @1, @2, @3, @4) select [fiscalreceiptid] [dbo].[fiscalreceipt] @@rowcount > 0 , [fiscalreceiptid] = scope_identity()',n'@0 datetime2(7),@1 int,@2 decimal(18,2),@3 decimal(18,2),@4 decimal(18,2)',@0='2016-02-08 15:05:43.9145089',@1=666,@2=1.70,@3=0,@4=0 

second query:

exec sp_executesql n'update [dbo].[fiscalreceipt] set [purchasetime] = @0, [cash] = @1 ([fiscalreceiptid] = @2) ',n'@0 datetime2(7),@1 decimal(18,2),@2 int',@0='2016-02-08 15:12:11.8101261',@1=555.00,@2=2042 

p.s. shouldn't there tm:rollback or tm:commit in eventclass column in sql profiler table when commited?

c# code:

note: outofpaperexception intended ignored , transaction inside scope being commited on purpose. changes should rolled on other exception.

var transaction = databasecontext.database.begintransaction();              try             {                 // commented debugging                 //ifiscalprinter fprinter = devicemanager.getfiscalprinter();                 //var lastreceiptnumber = fprinter.getlastreceiptnumber();                  // false data debugging                 var lastreceiptnumber = 666;                 receipt.receiptnumber = lastreceiptnumber++;                 receipt.purchasetime = datetime.now;                  databasecontext.savechanges();                  //fprinter.printfiscalreceipt(receipt);                  // exception debugging purpose                 if (receipt.cash < 500)                 {                     throw new exception();                 }                  transaction.commit();                  close();             }             catch (outofpaperexception)             {                 if (transaction != null)                 {                     transaction.commit();                     close();                 }                  messageboxservice.showmessage("promenite papir pre sledećeg štampanja!", "nema više papira!", messagebutton.ok, messageicon.warning);             }             catch (exception ex)             {                 // added doesn't                 receipt.purchasetime = new datetime();                 receipt.receiptnumber = 0;                 //receipt.fiscalreceiptid = 0; <- i'm not allowed                  if (transaction != null)                 {                     transaction.rollback();                 }                  messageboxservice.showmessage(ex.message, "greška!", messagebutton.ok, messageicon.error);             }                         {                 if (transaction != null)                 {                     transaction.dispose();                 }             } 

databasecontext lifetime equal viewmodel's lifetime.

edit: changing appropriate entry states entrystate.added results in successful operation, feels dirty. shouldn't entries remain in added state on transaction rollback/fail?

edit2: after running code:

using (metalshopdb ctx = new metalshopdb()) using (var transaction = ctx.database.begintransaction()) {     var receipt = new fiscalreceipt()     {         receiptnumber = 555,         purchasetime = datetime.now,         cash = 100     };      ctx.fiscalreceipts.add(receipt);      console.writeline("has changes " + ctx.changetracker.haschanges());     console.writeline(ctx.entry(receipt).state);      ctx.savechanges();      console.writeline("saved changes");      console.writeline("has changes " + ctx.changetracker.haschanges());     console.writeline(ctx.entry(receipt).state);      transaction.rollback();      console.writeline("rolled back");      console.writeline("has changes " + ctx.changetracker.haschanges());     console.writeline(ctx.entry(receipt).state); } 

i output, find strange, because 1 expect context in sync db, when rollback, context should follow changes.

has changes true added saved changes has changes false unchanged rolled has changes false unchanged 

for edit2

when savechanges methods called, if no error found when saving (which case since rollback after), objectcontext.acceptallchanges() methods invoked accept changes , populate primary keys, foreign keys , change entry state.

the rollback rollback transaction , not on object context / change tracker.

it's late @ point call savechanges again since entities populated database information if did rollback.

original question

you throw error (for debugging) after savechanges has been successfully completed

if (receipt.cash < 500) {     throw new exception(); } 

so following previous logic, acceptallchanges invoked.

edit

you can control acceptallchanges saving using objectcontext

var objectcontext = ((iobjectcontextadapter) ctx).objectcontext; objectcontext.savechanges(saveoptions.detectchangesbeforesave);  transaction.commmit(); objectcontext.acceptallchanges(); 

Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -