Skip to content

CreateTable adds redundant rowversion trigger when column marked as concurrency token #390

@harryKont

Description

@harryKont

When a column is marked as a concurrency token upon entity creation EF generates a migration that looks like this

migrationBuilder.CreateTable(
                name: "Table",
                schema: "Default",
                columns: table => new
                {
                    ID = table.Column<long>(type: "NUMBER(19)", nullable: false),
                    VERSION = table.Column<long>(
                        type: "NUMBER(19)",
                        rowVersion: true,
                        nullable: false
                    ),
                },

Generating the script using dotnet ef migrations script adds a trigger like this for the Version column

DECLARE
    v_Count INTEGER;
BEGIN
SELECT COUNT(*) INTO v_Count FROM "Default"."EF_MIGRATION_HISTORY" WHERE "MIGRATION_ID" = N'20240205231307_InitialCreate';
IF v_Count = 0 THEN

    CREATE OR REPLACE TRIGGER "Default"."rowversion_TABLE"
    BEFORE INSERT OR UPDATE ON "Default"."TABLE"
    FOR EACH ROW
    BEGIN
      :NEW."VERSION" := UTL_RAW.CAST_FROM_BINARY_DOUBLE(UTL_RAW.CAST_TO_BINARY_DOUBLE(NVL(:OLD."VERSION", '0000000000000000')) + 1);
    END;
END IF;
END;

/

However, when adding the same column after creation using AddColumn it is not adding the trigger

migrationBuilder.AddColumn<long>(
                name: "VERSION",
                schema: "OS",
                table: "ORDERS",
                type: "NUMBER(19)",
                rowVersion: true,
                nullable: false,
                defaultValue: 0L);

We would like to have more control over the row version trigger so we ended up using the second method.

Although this workaround worked for us I find it weird that the behaviour differs based on the way the column was added by the migration. This started happening at some point between EF Core 6 and 8 and it is a breaking change as with previous EF versions we didn't get the trigger automatically created by EF. We had to create it manually. In later versions EF started generating the trigger but this is problematic because every time we drop and recreate the DB it tries to add a trigger that was not there in the initial version. Ideally we would like to have more control of the rowversion trigger and be able to use our existing trigger (using a sequence) instead of the automatically created one that seems to just bump the existing row version column value on INSERT OR UPDATE

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions