I am upgrading an Asp.Net Core 1.1 application to Asp.Net Core 2.0.

I am getting a common error in all my Entity Framework 2.0 queries:

System.InvalidOperationException: The property 'Id' cannot be 
configured as 'ValueGeneratedOnUpdate' or 'ValueGeneratedOnAddOrUpdate'
because the key value cannot be changed after the entity has been 
added to the store.

This error is obtained with the following query:

var themes = await _context.Themes.ToListAsync();

Where Theme entity is the following:

public class Theme
{
    public Int32 Id { get; set; }

    public String Name { get; set; }

    public virtual ICollection<Book> Books { get; set; }
} // Theme    

And its configuration the following:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    builder.Entity<Theme>(b => 
    {
        b.ToTable("Themes");

        b.HasKey(x => x.Id);

        b.Property(x => x.Id).UseSqlServerIdentityColumn();

        b.Property(x => x.Name).IsRequired(true).HasMaxLength(200);

        b.HasIndex(x => x.Name).IsUnique();
    });
}

And on the project Startup I have the following:

services.AddDbContext<Context>(x => x.UseSqlServer(connectionString));

I tried with different queries and entities and I keep getting this error.

What am I missing?

1

There are 1 answers

0
ChW On

As far as I understood your question you have trouble to set up a auto increment for your Id property.

Just remove the line b.Property(x => x.Id).UseSqlServerIdentityColumn(); and b.HasIndex(x => x.Name).IsUnique(); because HasKey will already set up auto increment. For further information you could read this MS docs article - Keys (primary). I removed the table mapping too, because of table name pluralization is activated by default.

Your OnModelCreating should be like followed:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    builder.Entity<Theme>(b => {

        b.HasKey(x => x.Id);

        b.Property(x => x.Name).IsRequired(true).HasMaxLength(200);
    });
}

Only for readability I would prefer following code:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    var themeEntity = builder.Entity<Theme>();

    themeEntity.HasKey(x => x.Id);

    themeEntity.Property(x => x.Name)
        .HasMaxLength(200)
        .IsRequired(true);
}

A better way would be to extract entity configuration into own classes they implementing IEntityTypeConfiguration<T> (configuration separation).