Concurrency Tokens

Note

This page documents how to configure concurrency tokens. See Handling Concurrency Conflicts for a detailed explanation of how concurrency control works on EF Core and examples of how to handle concurrency conflicts in your application.

Properties configured as concurrency tokens are used to implement optimistic concurrency control.

Conventions

By convention, properties are never configured as concurrency tokens.

Data Annotations

You can use the Data Annotations to configure a property as a concurrency token.

public class Person
{
    public int PersonId { get; set; }

    [ConcurrencyCheck]
    public string LastName { get; set; }

    public string FirstName { get; set; }
}

Fluent API

You can use the Fluent API to configure a property as a concurrency token.

class MyContext : DbContext
{
    public DbSet<Person> People { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .Property(p => p.LastName)
            .IsConcurrencyToken();
    }
}

public class Person
{
    public int PersonId { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

Timestamp/row version

A timestamp is a property where a new value is generated by the database every time a row is inserted or updated. The property is also treated as a concurrency token. This ensures you will get an exception if anyone else has modified a row that you are trying to update since you queried for the data.

How this is achieved is up to the database provider being used. For SQL Server, timestamp is usually used on a byte[] property, which will be setup as a ROWVERSION column in the database.

Conventions

By convention, properties are never configured as timestamps.

Data Annotations

You can use Data Annotations to configure a property as a timestamp.

public class Blog
{
    public int BlogId { get; set; }

    public string Url { get; set; }
    
    [Timestamp]
    public byte[] Timestamp { get; set; }
}

Fluent API

You can use the Fluent API to configure a property as a timestamp.

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(p => p.Timestamp)
            .IsRowVersion();
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public byte[] Timestamp { get; set; }
}