Saturday, 15 February 2014

c# - How to separate parallel requests? -


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:

Enter image details here

Imagine the following scenario:

  1. 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.
  2. 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

    1. the user wants to remember the report;
    2. 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.

      No comments:

      Post a Comment