Etherman
Etherman

Reputation: 1867

Why is Entity Framework ConcurrencyStamp not using ROWVERSION/TIMESTAMP?

I am new to EF and previously engineered custom ORMs that use TIMESTAMP fields for concurrency and also determining records for synchronization to other databases.

Why does EF (Core) use nvarchar(max) to store what looks like a Guid?

i.e. why does EF do work that the DB could be doing instead?

The obvious thing is at some point (maybe when scaling up to multiple servers/databases) we want to store multiple Guids in there, and/or maybe it is simply because ROWVERSION/TIMESTAMP is not consistently implemented on the DBs targeted by EF?

(on a similar note why is the ID field nvarchar(450)?)

UPDATE:

migrationBuilder.CreateTable(
    name: "AspNetRoles",
    columns: table => new
    {
        Id = table.Column<string>(nullable: false),
        ConcurrencyStamp = table.Column<string>(nullable: true),
        Name = table.Column<string>(maxLength: 256, nullable: true),
        NormalizedName = table.Column<string>(maxLength: 256, nullable: true)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_AspNetRoles", x => x.Id);
    });

Upvotes: 2

Views: 2034

Answers (1)

user743382
user743382

Reputation:

This seems like a questionable design decision of ASP.NET Core Identity, not a problem in Entity Framework Core. They use public virtual string ConcurrencyStamp { get; set; }, but for RowVersion/Timestamp columns, Entity Framework uses byte[] with an additional annotation or mapping to make sure EF understands the value should be re-read after updates. From one of EF's own test files:

public class Two
{
    [Key]
    public int Id { get; set; }

    [StringLength(16)]
    public string Data { get; set; }

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

    public virtual C NavC { get; set; }
}

If you use EF yourself, you should be able to use RowVersion/Timestamp columns without any issues.

Upvotes: 1

Related Questions