I will try to explain this issue with a simplified console application example, although the actual project is an asp.net mvc3 application .
with the following tables:
Imagine the following scenario:
- The user creates a report (a line in
TestReport , where
text The report is
string content, and
ready is a
bool flag, if the report is ready to be processed); By default,
Ready is set to
False , that is not ready.
- The user wants to process the report, so he submits it;
Ready is set to
true .
The system has an opportunity to recall the report again, if it has not yet been processed. Therefore, when the report is missed,
Ready is set to
false , on the contrary, when the report is processed, then in
TestReportRef The report is referred to by the line, its
Id .
Now think that on one
- the user wants to remember the report;
- The report is added to the process list;
Soon because it can be together, errors can occur. The report will be
Ready ==
False and it will be referenced in
TestReportRef .
Here is a simple console example how it can be:
var dc = New TestDataContext ('my connection string'); Dc.teestReport.InsertOnSubmit (New TestReport {text = "My Report Content", Ready = True // Ready In One Time}); Dc.SubmitChanges (); Work Return Report = () = & gt; {Var _dc = New TestDetectx (CS); Var report = _dc.teestReport.FirstOrDefault (t = & gt; T. RD); If (report! = Null & amp; reports. TestReportRef.Any ()) {thread. Sleep (1000); Report.Ready = false; _dc.SubmitChanges (); }}; Accept Action Report = () = & gt; {Var _dc = New TestDetectx (CS); Var report = _dc.teestReport.FirstOrDefault (t = & gt; T. RD); If (report! = Null & amp; reports. TestReportRef.Any ()) {thread. Sleep (1000); _dc.teestReportRef.InsertOnSubmit (new test REPORTRef {FK_ReportId = report.Id}); _dc.SubmitChanges (); }}; Var Task 1 = New Work (Recall Report); Var task2 = new work (accept report); Task1.Start (); Task2.Start (); Task1.Wait (); Task2.Wait (); Foreign currency (in DC test report var t) {Console.WriteLine (string.Format ("{0} \ t {1} \ t {2}", TID, T. Test, T. Reddy )); } Foreach (var t in dc.teestReportRef) {Console.WriteLine ("Ref Id: \ t" + t.FK_ReportId); }
threads. Sleep (1000); is added to ensure this work will examine one and the same condition.
The example given may look strange, though, I hope, it should be understood how I'm dealing with.
How can I avoid it? Making repository singletons is not a good idea. Do I use some shared mutoes (one for all web requests) to separate writing jobs only? Or should I use a pattern in this kind of scenario?
This is a simple example of one of my scenarios, though there are many scenarios in which it can run in the same discrepancy. The best thing would be to make such an intersection impossible, I think.
Why not add a
version column on the report table? The current version of the work begins with tracking, when the task is finished, if the version is the same, is tracked, the operation is fine, otherwise the failure is unsuccessful. If the operation looks fine, then update version +1 to version This optimistic is a type of lock; That mutually seems to be a dispute, but they are not so often.
UPDATE
If you are using linqto sql then you might have a check on parameter
[column (UpdateCheck = UpdateCheck) .lways)] In your case the handling of concurrency can be useful.
- The user wants to process the report, so he submits it;
No comments:
Post a Comment