SuperJMN
SuperJMN

Reputation: 14002

Entity Framework Core RowVersion column not updating using PostgreSQL

I've set a RowVersion column for my entity but it seems that it isn't storing anything on creates or updates.

it have this configuration in the DbContext OnModelCreating:

 modelBuilder.Entity<Author>()
    .Property(a => a.RowVersion)
    .IsConcurrencyToken()
    .ValueGeneratedOnAddOrUpdate();

However, the RowVersion column is always NULL, even after an entity update / create.

By the way, I'm using PostgreSQL with the Npgsql Library (NuGet). In the docs, it says that PostgreSQL doesn't support computed values on add or update

Is it the reason why it doesn't work?

If so, why could we circumvent this limitation?

Also, I've tested with:

modelBuilder.Entity<Author>().Property<byte[]>("RowVersion")
    .HasColumnName(ShadowPropertiesDb.RowVersion)
    .IsRowVersion();

It results in the same problem.

Upvotes: 7

Views: 5453

Answers (1)

T. Czubaszek
T. Czubaszek

Reputation: 101

In PostgreSQL RowVersion is predefined as a column named "xmin".

Example property (only for Npgsql):

[ConcurrencyCheck]
[Column("xmin",TypeName = "xid")]
public long RowVersion { get; set; }

If you want the property to be byte[] type:

Step 1: Change property type to byte[]

[ConcurrencyCheck]
[Column("xmin",TypeName = "xid")]
public byte[] RowVersion { get; set; }

Step 2: Add converter in "OnModelCreating(ModelBuilder builder)"

var converter = new ValueConverter<byte[], long>(
     v => BitConverter.ToInt64(v, 0), 
     v => BitConverter.GetBytes(v));

builder.Entity<Author>()
   .Property(_ => _.RowVersion)
   .HasConversion(converter);

================ For many database type =================

Property:

[ConcurrencyCheck]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public byte[] RowVersion { get; set; }

In "OnModelCreating(ModelBuilder builder)":

if (Database.IsNpgsql())
{
    var converter = new ValueConverter<byte[], long>(
        v => BitConverter.ToInt64(v, 0),
        v => BitConverter.GetBytes(v));

    builder.Entity<Author>()
            .Property(_ => _.RowVersion)
            .HasColumnName("xmin")
            .HasColumnType("xid")
            .HasConversion(converter);
}

Upvotes: 9

Related Questions