Unable to update when primary key is character(x)
See original GitHub issueA DbUpdateConcurrencyException
occurs when an UPDATE
to a record with a fixed length character primary key is Saved to the DB and that key has trailing spaces. The Concurrency check appears to trim the value on the primary key which causes it to fail validation of the change even though the SQL log shows a valid UPDATE
command (with space padding) was received and processed. I have attached a small .NET Core Console application that generates the exception.
I have tried numerous ways to define the entity model but without success. Prior to this 2.1.1.1 release of Npgsql.EntityFrameworkCore.PostgreSQL I was able to make this work using a property definition of .HasColumnType("varchar").HasMaxLength(8)
which didn’t make sense but worked. Re-scaffolding the database using the 2.1.1.1 release outputs the property as .HasColumnType("character(8)")
with a string property.
Postgresql log:
2018-08-03 16:44:19 CDT LOG: execute <unnamed>: UPDATE testchar.tablechar SET char_value = $1 WHERE char_ident = $2
2018-08-03 16:44:19 CDT DETAIL: parameters: $1 = 'This will NOT update', $2 = '123456 '
Issue Analytics
- State:
- Created 5 years ago
- Comments:13 (9 by maintainers)
The thanks are all to you and the Npgsql team for finding the issue and correcting it so quickly. Fortunately this problem allowed me to convince the customer that some database structure changes should be made to overcome other conversion from Sybase issues.
@austindrenski your analysis here seems correct, we keep running into this issue again and again.
One new thought I’ve just had on this, is that there’s the theoretical possibility of relaxing the strong typing approach when it comes. Npgsql currently sends specific type OIDs for all parameters, but there’s also the option to send 0 (“unknown”), to allow PostgreSQL to infer the type from the context. This would make string parameters behave like literal strings above, and allow PostgreSQL type inference to do the right thing. Note that in EF Core literal representations are currently also always strongly-typed, except for strings (and numbers) as can see above: we don’t generate
'some_text'::TEXT
, but rather simplysome_text
. This was more a concern of readability, but also affects inference.I’m not sure I understand the exact consequences of not typing our parameters in this way. SQL where the context isn’t enough to infer would start failing; an example is
SELECT $1
, but there are surely some less-contrived real-world scenarios. This definitely merits some analysis, we could also simply send type OID 0 and see what it does to our current test suite 😃 Finally, note that this is really something that’s needed for EF Core (but possibly also other ORMs) rather than for Npgsql itself - if you’re working at the ADO.NET level you always have the option of explicitly setting the exact desired type viaNpgsqlDbType
.PS Here are the PostgreSQL docs on character types, documenting the bizarre truncation behavior with trailing whitespace.