An in-depth understanding of concurrent conflicts in asp.net core series

Time:2019-8-5

This article describes how to deal with conflicts when multiple users update the same entity concurrently.

There are two main types: one is to check for concurrent conflicts of attributes, using Concurrent Check; the other is to detect concurrent conflicts of rowversions, which track attributes and report errors if changes are made before saving.

Concurrent conflicts occur:

1. Users navigate to entity editing pages;

2. Before the changes of the first user are written to the database, another user updates the same entity;

At this point, if concurrent detection is not enabled, when an update occurs:

The last update takes precedence. That is, the last updated value is saved to the database. The first saved value will be lost.

For instance:

1. Jane visited the Department editing page and changed the budget of the English Department from $350,000.00 to $0.00 (the first user changed the amount to $0).

2. Before Jane clicked Save, John visited the same page and changed the start date field from 2007/1/9 to 2013/1/9. (Before the first user saves, the second user changes the time from 07 to 13 years, noting that the amount the second user sees is not yet zero)

3. Jane first clicks Save and sees her changes when the browser displays the index page. (The first user saves it first and can see his changes in the browser. The amount changes to 0 and the time remains unchanged.)

4. John clicks Save on the Edit page, but the page’s budget still appears at $350,000.00. (The second user saves the page at this time with a budget of less than $350,000 for 13 years)

In fact, the result depends onConcurrent Conflict Handling

First of all, this is an optimistic concurrent conflict, so what is an optimistic concurrent conflict?

Optimistic concurrent conflicts allow concurrent conflicts to occur and respond correctly when concurrent conflicts occur.

Having said so much, what about the way concurrent conflicts are handled?

1. You can track the user’s modified attributes and update only the corresponding columns in the database.

In this way, when two users update different properties, they will take effect the next time they view them.

However, there are some problems with this method:

  • Data loss cannot be avoided when competitive changes are made to the same attribute
  • Usually not suitable for web applications. It needs to maintain an important state in order to track all extracted and new values. Maintaining a large number of states may affect application performance.
  • It may increase application complexity (compared with concurrent detection on the entity).

As an example, the next time someone visits the English Department, they will see the changes made by Jane and John.

2. Client First

That is, the value of the client takes precedence over the value stored in the database. And if there is no coding for concurrent processing, the client will automatically take precedence.

That is, John’s changes override Jane’s changes. That is to say, the next time someone visits the English Department, they will see 2013/9/1 and extract a value of $350,000.00.

3. Storage First

This way, John’s changes in the database can be prevented. And you can

  • Display error message
  • Display the current status of data
  • Allow users to reapply changes.

Handling concurrency

When the attribute is configured as a concurrent token:

The database and data model must be configured to support triggering DbUpdate Concurrent Exception.

Detecting Concurrent Conflicts of Attributes

Concurrent Check features can be used to detect concurrent conflicts at the attribute level. This feature can be applied to multiple attributes on the model. [Concurrent Check] feature

Detecting concurrent collisions of issuance

To detect concurrency conflicts, add the rowversion trace column to the model.

Note: rowversion,

1. It is specific to SQL Server. Other databases may not provide similar functionality.

2. Used to determine that no entity has been changed after the entity has been extracted from the database.

The database generates rowversion serial numbers, which increase with each row update.

In the update or delete command, where clause includes the judgment of rowversion extraction value.

If the row to be updated has been modified, the rowversion extraction value does not match the rowversion value in the current database.

The update or delete command cannot find the line. Raise a DbUpdate ConcurrencyException exception

Example

Adding trace attributes to Department entities

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }
[StringLength(50, MinimumLength = 3)]
public string Name { get; set; }
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }
public int? InstructorID { get; set; }

1564977251
Public byte [] RowVersion {get; set;} // trace attribute

public Instructor Administrator { get; set; }
public ICollection<Course> Courses { get; set; }
}
}

The Timestamp feature specifies that this column is included in the where clause of the update and delete commands.

You can also specify trace attributes using the Fluent API:


modelBuilder.Entity<Department>()
.Property<byte[]>("RowVersion")
.IsRowVersion();

The following code shows the partial T-SQL generated by EF Core when updating the Department name:


SET NOCOUNT ON;

UPDATE [Department] SET [Name] = @p0
WHERE [DepartmentID] = @p1 AND [RowVersion] = @p2;

SELECT [RowVersion]
FROM [Department]
WHERE @@ROWCOUNT = 1 AND [DepartmentID] = @p1;

The previous code shows the WHERE clause containing RowVersion. If the database RowVersion is not equal to the RowVersion parameter (@p2)
The row is not updated.

@@ ROWCOUNT returns the number of rows affected by the previous statement. In the absence of row updates, EF Core triggers
DbUpdateConcurrencyException

The main purpose of this article is to facilitate their own record learning, if there are errors, you are welcome to correct.

References are attached here:

https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/concurrency?view=aspnetcore-2.2&tabs=visual-studio

The above is the whole content of this article. I hope it will be helpful to everyone’s study, and I hope you will support developpaer more.

  • EF Core verifies that attributes have not been changed after extraction. This check is performed when SaveChanges or SaveChangesAsync is called.
  • If the property is changed after extraction, DbUpdate Concurrent Exception is triggered.

Recommended Today

The method of obtaining the resolution of display by pyqt5

The code is as follows import sys from PyQt5.QtWidgets import QApplication, QWidget class Example(QWidget): def __init__(self): super().__init__() self.initUI() #Interface drawing to initui method def initUI(self): self.desktop = QApplication.desktop() #Get display resolution size self.screenRect = self.desktop.screenGeometry() self.height = self.screenRect.height() self.width = self.screenRect.width() print(self.height) print(self.width) #Show window self.show() if __name__ == ‘__main__’: #Create applications and objects app […]