Change 4 - Fix
I heard an answer from a member of the GitHub repository site, question 4512 . You must update the original value for the object. It can be done like this.
var passedInTimestamp = new byte[] { 0, 0, 0, 0, 0, 0, 0, 120 };
I updated the original unit test, which DbUpdateConcurrencyException when you and I could not get a DbUpdateConcurrencyException throw, now it works as expected.
I am updating my GitHub ticket to ask if they can make a change so that the generated sql code uses the new value instead of the original value when the column is marked as Timestamp or IsConcurrencyToken so that it behaves similar to previous versions of the Entity Framework.
So far, it seems like a way to do this with individual objects.
Edit # 3
Thanks, I missed it. After additional debugging, once again I fully understand the problem, although not why this happens. We should probably get the Web API out of it, although less mobile, and I don't think there is a direct relationship between the EF Core and the Web API. I reproduced this question with the following tests that illustrate the problem. I hesitate to call this a mistake, because perhaps the agreement to force EF Core to use the value passed to Timestamp has changed from EF6.
I created a complete set of working minimum codes and created a problem / question on the GitHub project site. I will include the test again below for reference. As soon as I hear the answer, I will send an answer to this answer and let you know.
Dependencies
- Sql Server 2012
- Ef core
- EntityFramework.Commands 7.0.0-rc1-final
- EntityFramework.MicrosoftSqlServer 7.0.0-rc1-final
DDL
CREATE TABLE [dbo].[Person]( [Id] [int] IDENTITY NOT NULL, [Title] [varchar](50) NOT NULL, [Timestamp] [rowversion] NOT NULL, CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED ( [Id] ASC )) INSERT INTO Person (title) values('user number 1')
Entity
public class Person { public int Id { get; set; } public String Title { get; set; }
Db context
public class Context : DbContext { public Context(DbContextOptions options) : base(options) { } public DbSet<Person> Persons { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Person>().HasKey(x => x.Id); modelBuilder.Entity<Person>().Property(x => x.Id) .UseSqlServerIdentityColumn() .ValueGeneratedOnAdd() .ForSqlServerHasColumnName("Id"); modelBuilder.Entity<Person>().Property(x => x.Title) .ForSqlServerHasColumnName("Title"); modelBuilder.Entity<Person>().Property(x => x.Timestamp) .IsConcurrencyToken(true) .ValueGeneratedOnAddOrUpdate() .ForSqlServerHasColumnName("Timestamp"); base.OnModelCreating(modelBuilder); } }
Unit test
public class UnitTest { private string dbConnectionString = "DbConnectionStringOrConnectionName"; public EFTimestampBug.Models.Context CreateContext() { var options = new DbContextOptionsBuilder(); options.UseSqlServer(dbConnectionString); return new EFTimestampBug.Models.Context(options.Options); } [Fact]