Я пытаюсь заставить RowVersion работать правильно как на SqLite, так и на SqlServer с помощью простого запроса к столбцу rowversion. Чтобы сделать это, мне нужно преобразовать столбец rowversion в ulong вместо byte [], и он по-прежнему должен работать должным образом.
public abstract class VersionEntity
{
public ulong RowVersion { get; set; }
}
public class Observation : VersionEntity
{
public Guid Id { get; set; }
public Guid TaskId { get; set; }
public string Description { get; set; }
public DateTime DueDate { get; set; }
public Severity Severity { get; set; }
}
public class TestDbContext : DbContext
{
public static string ConnectionString { get; set; } = "Data Source=dummy.db";
public DbSet<Observation> Observation { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Observation>().HasKey(o => o.Id);
modelBuilder.Entity<Observation>().Property(o => o.RowVersion).HasConversion(new NumberToBytesConverter<ulong>()).IsRowVersion();
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(ConnectionString);
optionsBuilder.UseLazyLoadingProxies();
}
}
В моей первой добавленной миграции изменилось RowVersion, чтобы иметь rowVersion: true (не добавляется автоматически). Также добавлено
private string _triggerQuery = @"CREATE TRIGGER Set{0}RowVersion{1}
AFTER {1} ON {0}
BEGIN
UPDATE {0}
SET RowVersion = current_timestamp
WHERE rowid = NEW.rowid;
END
";
migrationBuilder.Sql(String.Format(_triggerQuery, tableName, "UPDATE"));
migrationBuilder.Sql(String.Format(_triggerQuery, tableName, "INSERT"));
Таким образом, он создается с помощью триггеров для имитации возрастающего глобального значения SqlServer RowVersion.
Миграция работает, а первое сохранение работает
context.Database.Migrate();
var id = Guid.NewGuid();
context.Observation.Add(new Observation
{
Id = id,
Description = "Test description1",
TaskId = Guid.NewGuid(),
Severity = Severity.Low,
DueDate = DateTime.Now
});
context.Observation.Add(new Observation
{
Id = Guid.NewGuid(),
Description = "Test description2",
TaskId = Guid.NewGuid(),
Severity = Severity.Low,
DueDate = DateTime.Now
});
context.SaveChanges(); // This works, and saves data
var observation = context.Observation.FirstOrDefault(o => o.Id == id);
observation.Description = "changed.."; // Checking here will show a value on RowVersion property
context.SaveChanges(); // This fail with concurrency error
Ошибка параллелизма:Предполагается, что работа с базой данных затронет 1 строку (и), но фактически затронет 0 строк. Данные могут быть изменены или удалены, так как объекты были загружены. См. http://go.microsoft.com/fwlink/?LinkId=527962 для получения информации о понимании и обработке исключений оптимистичного параллелизма.
Я не могу понять, почему это должно быть проблемой. Кто-нибудь есть идеи, почему это не работает? Похоже, что выбранная сущность имеет значение в свойстве RowVersion. Но когда он сохранен, он думает, что изменился.