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);
    });
2
  • 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. Commented Dec 8, 2016 at 8:19
  • Here is another post with screen shot of data types: stackoverflow.com/questions/34252640/… Commented Dec 8, 2016 at 8:36

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.