-
Notifications
You must be signed in to change notification settings - Fork 225
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
Usage of xmin column as concurrency token #19
Comments
Submitted dotnet/efcore#5367 |
* uint (corresponds to oid, xid, cid) is now mapped to oid by default. * System columns (oid, xid, etc.) are now ignored in ModelDiffer so that no migrations are generated for them. Relates to #19
Reopening to introduce an extension method which would allow the following: modelBuilder.Entity<Chassis>().UseXminAsConcurrencyToken(); As a shortcut for: modelBuilder.Entity<Chassis>(b =>
{
b.Property<uint>("xmin")
.HasColumnType("xid")
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken();
}); |
Using the extension method does not work for Code First migrations. It causes the column to be added in the migration which causes the migration to fail. For example:
I tried adding It is possible to manually remove the |
An AddColumn migration may get created, but it should get ignored by the migration SQL generator (so there will be no DDL which attempts to create the column). What error exactly did you get? |
Sorry, I should have been more thorough. This is the error I get in the package manager console when applying the migration (via
I'm using For the above migration, the only configuration change is adding |
I have same issue as @jgilm has. Is it ok now to remove AddColumn() with "xmin" from migration? |
I've added a new issue #145 with the comments copied. Thanks! |
Oops, I have just called this method and I'm getting added the xmin column in a migration!
I thought this was fixed long ago! |
Any one has any example code sample of implementing the concurrency in ef core with generic repository. Please share. |
Guys - as I wrote above, the migration may get generated, but it should be ignored when you actually run it. Have you actually tried to update the database, are you seeing an error? |
Hi, What is exactly required to have optimistic concurrency with Entity Framework Core 2.0 and PostgreSql? Calling UseXminAsConcurrencyToken() and catch exceptions of type DbUpdateConcurrencyException (with a retry mechanism) doesn't seem to be sufficient. Should I do anything else with xmin? At roji (or somebody else): Can you provide a small example? |
Why not exactly? What exactly are you expecting out of optimistic concurrency beyond an exception when a concurrent update occurs? xmin is only an auto-updating column that allows EF Core to detect that a change occurred by someone else - you're definitely not supposed to examine it yourself or do anything with it. Read the docs for more detail on optimistic concurrency. |
@roji you definitely need to examine and "do things" with the concurrency token in an asp.net webapi scenario. You seem to be forgetting web server scenarios where the client must provide the concurrency token, which means it needs to get it, store it and send it back to be rehydrated at the server so that concurrency checking can work. This also might explain why I'm struggling to get this ForNpgsqlUseXminAsConcurrencyToken() method to work if it was written without regard to disconnected client scenarios as is common with asp.net applications. |
I couldn't get the ForNpgsqlUseXminAsConcurrencyToken() method to work with a disconnected WebApi client and migrations are not an issue for me, but for any future users looking into this ... This worked for me with a web api client supplying the token on update: Model: public partial class Widget
{
public long Id { get; set; }
public uint ConcurrencyToken { get; set; }
public string Name { get; set; }
...etc... In OnModelCreating: modelBuilder.Entity<Widget>()
.Property(e => e.ConcurrencyToken)
.HasColumnName("xmin")
.HasColumnType("xid")
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken(); And in the controller this will update the original value of the concurrency token to trigger checking: ct.Entry(oFromDb).OriginalValues["ConcurrencyToken"]=oIn.ConcurrencyToken; |
@WhatFreshHellIsThis I understand what you're saying, and your sample should definitely work, can you please open a new issue for that and I'll take a look? If you can include a minimal code sample (without web) that would be even better. |
I'm not sure there is a solution you can do with that single ForNpgsqlUseXminAsConcurrencyToken() call because the model needs the concurrency token and needs to be able to set it on update. Unless I'm mistaken the ForNpgsqlUseXminAsConcurrencyToken() method will only ever be viable for a permanently connected client where the concurrency token doesn't need to be managed in the developers code. |
I'm not sure I understood that last part... PostgreSQL is responsible for updating the value of xmin every time a row is modified - and EF Core retrieves that new value. As long as your application copies the original value of xmin, and then, after reconnecting with a new dbcontext, injects that into the change tracker as you showed above, EF Core should emit the proper query checking the original xmin value, no? I don't see why there should be a problem here... |
Okay the following works fine, as long as the property in my Entity is called xmin:
But I want to have a different name for my property, let's say "ConcurrencyToken". Now I do this:
During migration this also leads to an empty migration file, so that's okay. But when I call Add on the context, I get an error message
I tried all kind of things, but can't get it to work. What should I do to get it to work? An example would be great. |
I'm starting to play with Postgres, I've created an entity with attributes on property (with no Fluent). Seems to work ok- xid column in DB, Rowversion property in class (you can use your ConcurrencyToken):
|
In an effort to provide further help (since this was one of the first links from google about concurrency tokens in postrgres using ef core), I expanded on @WhatFreshHellIsThis solution, and provided a more complete example here. I hope this helps anyone like me who is new to both ef core and postgresql! |
@mikylebaksh The whole point is a disconnected scenario. Unless I'm mistaken, your example doesn't bring anything new to the table that I didn't already post here in this thread. |
From @roji on April 4, 2016 8:7
Although PostgreSQL has no native support for computed columns, tables implicitly include an
xmin
system column which can be used as a rowversion or concurrency token. Probably need to treat it as a shadow property.Copied from original issue: npgsql/npgsql#1016
The text was updated successfully, but these errors were encountered: