I'm using Entity Framework, model first, self-tracking entities with Npgsql provider (VS2010 - .NET 4 target).
I'm trying to track optimistic concurrency exceptions, but my problem is that as soon as a column in the entity is marked as fixed, an OptimisticConcurrencyException is raised, even if the affected rows > 0.
After some digging exposed here, I would like to know why Entity Framework is issuing the update command through dbCommand.ExecuteReader(CommandBehavior.SequentialAccess) followed by a dbDataReader.Read() instead of dbCommand.ExecuteNonQuery() when the command text is a simple update statement ?
UPDATE "schema"."table"
SET "bool_column" = FALSE
WHERE ("id" = 7526) AND ("xmin" = 1249804)
Thanks.
The underlying provider should issue a SELECT statement right after an INSERT or UPDATE statement if there are any computed columns (StoreGeneratedPattern = "Computed" or "Identity") to retrieve.
Npgsql currently support only SERIAL during an INSERT operation.
It does not support computed column retrieval during an UPDATE operation. The consumer should call Refresh(RefreshMode.StoreWins, entity) to get values from the datasource.
This implies that Optimistic Concurrency is not supported in the current version of the Npgsql provider.
Related
Say I have EntityFramework Core 2.1.14.
Say I have to integrate data into a legacy MySql database which was created by a self-taught.
Say also that one of the tables in this database has a surrogate key field that is generated on Add.
Say then that I want to use context.SaveChanges() to handle the Insert DML generation for me because I want to be lazy and because these tables are messy.
Say finally that I do not want Entity Framework to perform a follow-up query to retrieve this surrogate field; I don't care what it is. I just need it generated on insert.
How would one call context.SaveChanges() with an Added object having a property configured as .ValueGeneratedOnAdd() but also instruct Entity Framework to do nothing but generate my INSERT ? I don't want it to return the id.
Using Entity Framework Core 3.0 and facing an odd issue where EF will throw an exception if I try to update an entity with ID=0, it thinks that ID=0 is a temporary value. Same code updates entity with ID=1 or higher without any problems.
Exception:
InvalidOperationException: The property 'Id' on entity type 'MyType' has a temporary value
while attempting to change the entity's state to 'Modified'. Either
set a permanent value explicitly or ensure that the database is
configured to generate values for this property.
Exception is triggered on the following statement:
_context.Attach(MyType).State = EntityState.Modified;
I don't want to reseed all my tables to start with 1.
Is this expected behavior with EF? It should be possible to save entities with ID=0.
Any advice on how to resolve this?
Thanks.
You have to do something about this zero ID value. It's a ticking time bomb.
You'll always have to be on your guard because it definitely is expected behaviour. EF has inner logic depending on key default values. In EF6 you could do this because it was less refined. (In this area that is).
Let me show you how leaving this ID value can backfire on you in the future.
You have this MyType object. Let's call it entity to follow some naming conventions/habits. Its ID value is 0 and it's not attached to the context.
Now suppose you don't use this rather redundant way to attach it as modified but the new EF-core way:
context.Update(entity);
Now you won't see any exception, but no, the issue isn't fixed. It's gotten worse. The entity object's state is Added now and you're going to add a new record to your table. That might even go unnoticed for a while, adding to the pile of mess you have to clean up later.
Had its ID value been > 0, EF's Update method would have concluded it's an existing entity and its state should be Modified.
You can set entity's state to Modified if (1) it's not attached and (2) you use...
context.Entry(entity).State = EntityState.Modified;
And that's another time bomb. Later code changes remove the first condition (it's not attached) and boom.
This is Entity Framework 6.1.3 with .NET v4.0 and SQL Server 2008 R2.
In my, DB I have hundreds of tables with column LastChangedByUser in which I store the login of the user who last updated the row.
Unfortually, I have legacy triggers FOR UPDATE on almost all tables, and they all verify IF UPDATE(LastChangedByUser) and raise an error if this column is not included in the SET clause of the updated. I suppose the original developers did this to make sure the developers included every required column in their manually-written update queries.
By default EF only includes the properties that had their values changed when generating the SET clause of an UPDATE query. And this is causing problems in the following scenario: If previously some row was last changed by "user1", and the same "user1" tries to updates this row again later, EF is not including the LastChangedByUser column in it's generated SET clause, since it was set to the same value that it previously had. And the trigger is raising the error.
My legacy system (pre-EF) includes the LastChangedByUser in the SET clause in manually-written queries, regardless of the value being unaltered, so the trigger validations do OK for those old queries.
So I need to "mimic" this behavior in Entity Framework: if the code explicitly set a property value of a bound Entity proxy, I need its corresponding DbPropertyEntry to have the IsModified set to true regardless of the value being the same as the previous value.
I don't want to include all the columns in the SET cause (I tried this and had other trigger problems). I just want to include the columns that were set explicitly, like:
//this should make the property IsModified become true
//even if it was already "user1" when the entity loaded
myEntity.LastChangedByUser = "user1";
If the code simply dos not change the property (the setter is never called), then the property should remain with IsModified == false.
Is it possible to solve this? Maybe this default behaviour is too intrinsic and can't be changed...
Unfortunately I cannot just disable/drop the triggers, since they do tons of business rules on which the legacy system is dependent. And they are hundreds, so editing each one of them will be really tough...
Thank you!
Recently i upgraded from EF5 to EF6 and here is list of items which one needs to take care of
EF MiniProfiling: if you were using mini profiling with EF5 you will have broken code as few of the functiionality or variable names had been changed.
Resolution: Upgrade to newer version of EF MiniProfiling
Db-Reindexing: After updating to EF6 it complaints you about change in your model and when you do "Add-Migration" you will see all your index for primary key were getting recreated also its changing name of tables where you have one to one relationship so previously if it generates table name as TableATableB then it will rename table as TableBTableA dont know why.
Resolution 1: Let EF create migrations for create index , just comment out line in
up and down function.
Resolution 2: Copy line of code from down function(i.e. drop index) and try to execute it before it create index , simple rule first drop and then create, you need this else EF will complaint about index already present.
Migrations: This will only affect you if you are doing using some tool to deploy you assemblies and which in turns uses migrate.exe typically found at
...#your project location\packages\EntityFramework.6.1.0\tools\migrate.exe
copy it to your bin folder and things should work fine.
4. Null Handling: In EF6 handling of null values had been changed , my hands on experience says that with ef5 select query was ignoring null cases but is not the case with ef6
e.g. if i have query something like
db.context.entity.where(name != "ab");
and lets say entity table contains two names {"ab",null}
with EF5 it will return 1 row with ef6 it was returning 2 rows
http://entityframework.codeplex.com/workitem/2115
Resolution: If you wanted to work exactly like EF5 you can set
dbContext.Configuration.UseDatabaseNullSemantics = true;
If it helps please don't forgot to mark this post as answered :)
I've created a view in my database which I would like to include in my entity model. However, when I try to update the entity model through VS 2008, a warning message informs me that the TABLE OR VIEW I'm trying to add doesn't have a primary key.
It seems that in order to add a view to the model, this must have a key field! How can I add this view to my model if views are not permitted to have key field, at least in firebird which is the DBMRS I’m using.
Any idea of how to solve this?
There's a great answer to that here: Entity Framework and SQL Server View (see accepted answer: https://stackoverflow.com/a/2715299/53510.)
EF infers a PK for views by combining all non-nullable fields. You can use ISNULL and NULLIF to manipulate the nullability of view columns thereby forcing EF to pick the PK you want.
There is no keys in firebird views. Instead, set one (or more) field as 'not null' with the following command:
update RDB$RELATION_FIELDS set RDB$NULL_FLAG = 1 where (RDB$FIELD_NAME = 'A_FIELD') and (RDB$RELATION_NAME = 'A_VIEW')
Then re-import the database in entity framework.