Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
harryKont opened this issue Jul 2, 2024 · 1 comment

Comments

@harryKont
Copy link

harryKont commented Jul 2, 2024

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

@alexkeh
Copy link
Member

alexkeh commented Jul 2, 2024

Which two ODP.NET EF Core versions exhibited the behavior difference? Presumably, you upgraded from one version to another to see the issue.

You can turn on EF Core tracing or ODP.NET tracing to see the difference in what the providers are generating for their scripts and perhaps some basis for that difference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants