I have an intermittent Devart.Data.Linq.ChangeConflictException: Row not found or changed
raising it's ugly head. The funny thing is, the change is still written to the database!
The stack trace says:
Devart.Data.Linq.ChangeConflictException: Row not found or changed. at Devart.Data.Linq.Engine.b4.a(IObjectEntry[] A_0, ConflictMode A_1, a A_2) at Devart.Data.Linq.Engine.b4.a(ConflictMode A_0) at Devart.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) at Devart.Data.Linq.DataContext.SubmitChanges() at Billing.Eway.EwayInternal.SuccessCustomerRenewal(String username, Bill bill, EwayTransaction transaction)
And my code for Billing.Eway.EwayInternal.SuccessCustomerRenewal
:
internal static void SuccessCustomerRenewal(string username, Bill bill, EwayTransaction transaction) { ApplyBillToCustomerAccount(username, bill, true); using (MsSqlDataClassesDataContext msSqlDb = new MsSqlDataClassesDataContext()) { EwayCustomer ewayCustomer = msSqlDb.EwayCustomers.First(c => c.Username == username); ewayCustomer.NextBillingDate = Common.GetPlanExpiry(bill.BillPlan); using (MySqlDataContext mySqlDb = new MySqlDataContext()) { BillingMySqlContext.Customer grasCustomer = mySqlDb.Customers.First(c => c.Username == username); grasCustomer.MembershipDate = ewayCustomer.NextBillingDate.AddDays(1); mySqlDb.SubmitChanges(); // <--- Problem is here } msSqlDb.SubmitChanges(); } BillingEmail.SendRenewalSuccessEmail(username, bill, transaction); }
I know that the issue occurs on the mySqlDb.SubmitChanges()
line, since that DB context is the one using Devart (Linq solution for MySQL databases): the other context uses pure MS Linq.
Not only is the change written to the MySql DB (inner using
block), but it is also written to the MsSql DB (outer using
block). But that's where the magical success ends, the email doesn't get sent and execution stops for the calling method.
If I could I would write a Minimal, Complete and Verifiable example, but strangely I'm unable to generate a Devart ChangeConflictException.
So, why does the change get saved to the database after a Devart.Data.Linq.ChangeConflictException
? When I previously encountered System.Data.Linq.ChangeConflictException
changes weren't saved.
Edit 1:
I've also now included the .PDB file and gotten line number confirmation of the exact source of the exception.
Edit 2:
I now understand why I can't generate a ChangeConflictException
, so how is it happening here?
These are the attributes for MembershipDate
:_
[Column(Name = @"Membership_Date", Storage = "_MembershipDate", CanBeNull = false, DbType = "DATETIME NOT NULL", UpdateCheck = UpdateCheck.Never)]
I know I can explicitly force my changes through to override any potential conflict, but that seems undesirable (I don't know what I would be overriding!). Similarly I could wrap the submit in a try
block, and retry (re-reading each time) until success, but that seems clunky. How should I deal with this intermittent issue?
Edit 3:
It's not caused by multiple calls. This function is called in one place, by a single-instance app. It creates log entries every time it is run, and they are only getting created once. I have since moved the email call to the top of the method: the email only gets sent once, the exception occurs, and database changes are still made.
I believe it has something to do with the using
blocks. Whilst stepping through the debugger on an unrelated issue, I entered the using
block, but stopped execution before the SubmitChanges()
call. And the changes were still written to the database. My understanding was that using
blocks were to ensure resources were cleaned up (connections closed, etc), but it seems that the entire block is being executed. A new avenue to research...
But it still doesn't answer how a ChangeConflictException
is even possible given Devart explicitly ignores them.
Edit 4:
So I wasn't going crazy, the database change did get submitted even after I ended execution in the middle of the using
block, but it only works for websites.
0 comments:
Post a Comment