3

I have a database table where one of the columns is an IDENTITY column (not the primary key which is set manually). My EF Core model looks like this:

public class Model
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }

    ...Other fields...

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

Despite the annotation, when I do an update on the table I find that the SQL which is generated tries to update the IDENTITY column:

UPDATE [Model] SET ... [AnotherId] = @p10 ...
WHERE [Id] = @p29;
SELECT @@ROWCOUNT;

This obviously fails, causing the an exception to be thrown. I am using Entity Core 2.0 and upgrading to 2.1 is currently not an option. Any ideas why the data annotation is being ignored?

Salah Akbari
  • 39,330
  • 10
  • 79
  • 109
SBFrancies
  • 3,987
  • 2
  • 14
  • 37

3 Answers3

5

The solution for me in EF Core 3.1 was this:

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<YourTableName>().Property(c => c.YourPropertyName).UseIdentityColumn().ValueGeneratedOnAddOrUpdate();
    }

Without ValueGeneratedOnAddOrUpdate() I was seeing the same error as the OP when updating existing records. It looks therefore as though UseIdentityColumn() is equivalent to calling ValueGeneratedOnAdd().

Nugsson
  • 196
  • 2
  • 12
4

Try Fluent API in OnModelCreating of the Context class. Something like this:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
    .Entity<Model>()
    .Property(c => c.AnotherId )
    .UseSqlServerIdentityColumn();
}

Also in EF Core 2 it should be something like this:

modelBuilder.Property(c => c.AnotherId).UseSqlServerIdentityColumn();
modelBuilder.Property(p => p.AnotherId )
            .Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
Salah Akbari
  • 39,330
  • 10
  • 79
  • 109
  • Thanks, this looks like a good answer but I have been using attributes over the fluent API where possible so I'm going to go with the solution suggested by @mjwills in the comments. – SBFrancies Jul 23 '18 at 10:25
  • @SBFrancies *Fluent API is another way to configure your domain classes. Fluent API provides more functionality for configuration than DataAnnotations.* https://www.tutorialspoint.com/entity_framework/entity_framework_fluent_api.htm – Salah Akbari Jul 23 '18 at 10:26
  • Thanks, I know that and am using the Fluent API to fill in the gaps where it is not possible to use data annotations. I just prefer to use the data annotations where possible and have found for the most part they have met my needs. – SBFrancies Jul 23 '18 at 10:32
  • As a note, these extension methods should be in the Microsoft.EntityFrameworkCore.SqlServer assembly. – Jeremy Holovacs Sep 10 '18 at 14:51
1

The attribute you likely want to use is:

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]

as per the docs.

mjwills
  • 23,389
  • 6
  • 40
  • 63
  • Thanks for this, I'm still not clear in the documentation where it shows that the expereinced behavior should be happening for `[DatabaseGenerated(DatabaseGeneratedOption.Identity)]` but this solved my issue for now. – SBFrancies Jul 23 '18 at 10:28