2

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);
    });
Etherman
  • 1,777
  • 1
  • 21
  • 34
  • EF shouldn't be using `nvarchar(MAX)` for that, and in EF6, it didn't. There could be a configuration problem somewhere, but if this really changed in EF Core, I suspect it's a bug, not a feature. Can you show your class definition and mapping, and the generated table? Aside: "(on a similar note why is the ID field nvarchar(450)?)" -- That's unrelated and probably best to leave out, but note that you should be able to spot the problem in SQL Server's warnings if you simply make it `nvarchar(MAX)` outside of EF. –  Dec 08 '16 at 08:19
  • Here is another post with screen shot of data types: http://stackoverflow.com/questions/34252640/what-is-the-purpose-of-the-concurrencystamp-column-in-the-aspnetusers-table-in-t – Etherman Dec 08 '16 at 08:36

1 Answers1

1

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.

  • I'm usually guilty of trying to implement new frameworks in a rush and then re-inventing the wheel (badly no doubt) when I don't understand some standard/convention. I'm trying to avoid that here. There must be some reason to use strings here, I'm wondering what that is seeing as a large part of my project will include scalable concurrency and synchronization concerns. But I agree with you, now looks to me like a design choice in Identity not specifically EF. – Etherman Dec 08 '16 at 09:08