arch / AutoHistory

A plugin for Microsoft.EntityFrameworkCore to support automatically recording data changes history.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Concurrency Exception when using pack v6.0.0 in Nuget

LinQiaoPorco opened this issue · comments

Ef Core shows the AutoHistory require to have 'rowId' not follow the updated entity's Id, but the 'last_insert_rowid()', what does it mean?

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (1ms) [Parameters=[@p0='?' (Size = 56), @p1='?' (DbType = DateTime), @p2='?' (DbType = Int32), @p3='?' (Size = 1), @p4='?' (Size = 11)], CommandType='Text', CommandTimeout='30']
      INSERT INTO "AutoHistory" ("Changed", "Created", "Kind", "RowId", "TableName")
      VALUES (@p0, @p1, @p2, @p3, @p4);
      SELECT "Id"
      FROM "AutoHistory"
      WHERE changes() = 1 AND "rowid" = last_insert_rowid();

The result is that, 'RowId' was forced to be the same as 'Id' in AutoHistory. Or it will throw Concurrency Exception.
So the AutoHistory looks like this, all records happened to have same 'Id' and 'RowId' will insert with success, others fail with exception.

Id RowId TableName Changed Kind Created
1 1 GenericUser {"before":{"Function":null},"after":{"Function":"LPL"}} 3 2022-12-21 06:29:54.4720725
2 2 GenericUser {"before":{"Function":null},"after":{"Function":"LPL"}} 3 2022-12-21 12:42:43.4858065
3 3 GenericUser {"before":{"Function":null},"after":{"Function":"ICX"}} 3 2022-12-22 01:48:10.653962
4 4 GenericUser {"before":{"Function":null},"after":{"Function":"Battery"}} 3 2022-12-22 01:51:59.7880273
5 5 GenericUser {"before":{"Function":"Ext"},"after":{"Function":"LPL"}} 3 2022-12-22 01:52:59.1114256

Wondering that if the 'PrimaryKey' produced the 'RowId' with certain restrictions?

private static string PrimaryKey(this EntityEntry entry)
        {
            var key = entry.Metadata.FindPrimaryKey();

            var values = new List<object>();
            foreach (var property in key.Properties)
            {
                var value = entry.Property(property.Name).CurrentValue;
                if (value != null)
                {
                    values.Add(value);
                }
            }

            return string.Join(",", values);
        }

Root Cause tageted:
SQLite (or EF Core?) somehow regard the 'RowId' equivalent to 'Id' for 'AutoHistory' class, so it forces those 2 values shall be the same, or it will throw out concurrency exception, causing the SQL 'INSERT AutoHisoty...' fail.

Solution:
Change the name of AutoHistory.cs property 'RowId' to 'RowNumber' or other names, then add new migrations and update database, issue was solved.