Auto increment non key value entity framework core 2.0

.net-core c# entity-framework entity-framework-core

Question

I've got an object that has a key stored as a GUID as well as a friendlyID, like this:

public class Job {

    [Key]
    public Guid Id { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int FriendlyId { get; set; }

    public string Description { get; set; }
}

However when I try to update description using my update method:

    public void Update(Job job, Job jobParam) {
        if (job == null) {
            throw new AppException("Job does not exist");
        }

        //Update job properties
        job.Description = jobParam.Description;


        _context.Job.Update(job);
        _context.SaveChanges();
    }

I get an error stating:

System.Data.SqlClient.SqlException: Cannot update identity column 'FriendlyId'

I've made sure that the correct object is trying to be updated, but I can't understand why friendlyID would try to get updated when it has not been changed. When looking online I can see that there was a bug in EF core 1.1 that would cause this issue to occur, but nothing about 2.0 or about a value that isn't a key.

1
6
2/7/2018 2:39:51 PM

Accepted Answer

The exact behavior of the generated properties in EF Core is still in a process of tweaking. EF Core 2.0 introduced two new property metadata properties - BeforeSaveBehavior and AfterSaveBehavior. There is no data annotation/fluent API for setting them and by default they are implied from value generating strategy and whether the property is part of the key. At the same time they affect the behavior of the tracking operations.

The problem here is that for identity columns (i.e. ValueGeneratedOnAdd) which are not part of a key, the AfterSaveBehavior is Save, which in turn makes Update method to mark them as modified, which in turn generates wrong UPDATE command.

To fix that, you have to set the AfterSaveBehavior like this (inside OnModelCreating override):

modelBuilder.Entity<Job>()
    .Property(e => e.FriendlyId)
    .ValueGeneratedOnAdd()
    .Metadata.AfterSaveBehavior = PropertySaveBehavior.Throw; // <--
4
2/7/2018 3:31:09 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow