How do I get Entity Framework to only update the Properties modified in the SQL generated? - entity-framework

I am using Entity Framework with the Self-Tracking Entity T4 templates, which by default will generate a SQL Query setting all the properties on the Entity in an UPDATE statement. I only want an UPDATE statement that contains the properties modified.
I modified the T4 Template as specified in the book: Entity Framework Recipes: A Problem-Solution Approach page 503.
I changed to this line in the T4 Template:
OriginalValueMembers originalValueMembers = new OriginalValueMembers(false, metadataWorkspace, ef);
Making the Entity track each property change instead of just tracking that the Entity changed.
And also
context.ObjectStateManager.ChangeObjectState(entity, EntityState.Unchanged);
After making these changes I got the desired result of SQL statement with only the modified values/properties in the UPDATE statement. However, there was a strange side effect. When updating a nullable INT property from null to something other than null, the change of that was ignored by Entity Framework. The Self-Tracking Models show the change in the ChangeTracker with the accurate OriginalValue null, but when Entity Framework tried to generate the UPDATE SQL it did not see that property change if the original value null and the new value is not null. I worked if the original value was not null and value gets changed.
It seems to work ok on a string property going from null to a non-null value, but int? is not working.
Does anyone have any ideas?

If helpful, have found post that fixes this: fix update of nullable column.

Related

Entity Framework Update Fails for Entity With ID of 0

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.

How to create RowVersion column for optimistic concurrency using model first approach?

I am working on a legacy web app which implements model first(edmx file) approach using Entity Framework.
I need to implement optimistic concurrency, so I have added this field as following:
and inside the database has been created as binary(8) type.
But when I try to update the entity is getting updated but the VersionRow values is not updated(no new value generated).
P.S
When I added the column I have binded default value as 0x0000000000000000 because it does not allow null values.
Yea I solved it this way:
1) I changed the type of RowVersion column from Binary(10) into timestamp inside SqlServer.
2) In the property details inside the .edmx file I have put the property StoreGeneratedPattern of the property RowVersion as Computed.
Computed it means that a new value is generated on insert and update.
Now it became as following:

How to preserve non-nullable setting in edmx when refreshing model?

I have a project that I recently migrated from VS2010 to VS2012.
It contains an EF4.1 edmx file containing my entities. A few of these entities are based on views and are read-only. Although some columns returned by the views are nullable, I have changed the return value of these columns in the view to ensure that they do not return null by using
ISNULL(NumericColumnName, 0) AS NumericValueColumn
When updating the model via the "Update Model From Database" function in VS2010, the columns that were returned in this way were being created as non-nullable in my model. However, since the move to VS2012, this is no longer the case.
Now, whenever I use the "Update Model From Database" functionality, these properties are generated as nullable. What I have to do is manually set the columns to non-nullable. However, the entity properties will be regenerated as nullable the next time that I run "Update Model From Database". I then have to update them to non-nullable again.
Another work-around that I have tried is to move the view-based entities to their own edmx file. However, I am seeing the same behavior when updating either of the edmx files.
Another detail is that I am using Self-Tracking Entities, generated via the EF4.1 T4 STE templates.
Is there any way to prevent the VS2012's EF designer from overwriting my non-nullable attribute for the view-based entities?
EDIT
It turns out that the designer in VS2012 is trying to prevent you from shooting yourself in the foot, and consequently changes the member properties inside my entity.
When generating a member from the following:
SELECT ISNULL(Quantity,0) * ISNULL(Number, 0) AS Total FROM SomeTable
VS2012 will always set the member Total on the SomeTable entity to nullable because it does not understand that there is no way for the result of the multiplication to be 0. To prevent this behavior, change it to:
SELECT ISNULL(Quantity * Number, 0) AS Total FROM SomeTable.
Watch out for aggregations as ISNULL(SUM(SomeCol),0) is not the same as SUM(ISNULL(SomeCol,0)).

Entity Framework 5 SaveChanges Not Working, No Error

None of the many questions on this topic seem to match my situation. I have a large data model. In certain cases, only a few of the fields need be displayed on the UI, so for those I replaced the LINQ to Entity query that pulls in everything with an Entity SQL query retrieving only the columns needed, using a Type constructor so that I got an entity returned and not a DbDataRecord, like this:
SELECT VALUE MyModelNameSpace.INCIDENT(incident.FieldA, incident.FieldB, ...) FROM ... AS ...
This works and displays the fields in the UI. And if I make a change, the change makes it back to the entity model when I tab out of the UI element. But when I do a SaveChanges, the changes do not get persisted to the database. No errors show up in the Log. Now if I very carefully replace the above query with an Entity Sql query that retrieves the entire entity, like this:
SELECT VALUE incident FROM MyDB.INCIDENTs AS incident...
Changes do get persisted in the database! So as a test, I created another query like the first that named every column in the entity, which should be the exact equivalent of the second Entity SQL query. Yet it did not persist changes to the database either.
I've tried setting the MergeOption on the returned result to PreserveChanges, to start tracking, like this:
incidents.MergeOption = MergeOption.PreserveChanges;
But that has no effect. But really, if retrieving the entire entity with Entity Sql persists changes, what logical purpose would there be for behaving differently when a subset of the fields are retrieved? I'm wondering if this is a bug?
Gert was correct, the problem was that the entity was not attached. Dank U wel, Gert! Ik was ervan verbluft!
I just wanted to add a little detail to show the full solution. Basically, the ObjectContext has an Attach method, so you'd think that would be it. However, when your Entity SQL select statement names columns, and you create the object using a Type as I did, the EntityKey is not created, and ObjectContext.Attach fails. After trying and failing to insert the EntityKey I created myself, I stumbled across ObjectSet.Attach, added in Entity Framework 4. Instead of failing, it creates the EntityKey if it is missing. Nice touch.
The code was (this can probably be done in fewer steps, but I know this works):
var QueryString = "SELECT VALUE RunTimeUIDesigner.INCIDENT (incident.INCIDENT_NBR,incident.LOCATION,etc"
ObjectQuery<INCIDENT> incidents = orbcadDB.CreateQuery<INCIDENT>(QueryString);
incidents.MergeOption = MergeOption.PreserveChanges;
List<INCIDENT> retrievedIncidents = incidents.ToList<INCIDENT>();
orbcadDB.INCIDENTs.Attach(retrievedIncidents[0]);
iNCIDENTsViewSource.Source = retrievedIncidents;

Cannot insert NULL into a non-identity column in Entity Framework. Funny thing... it's not null?

I have a SalesOrder table with columns for ID and OrderID. ID is an auto-generated int. OrderID is a non-nullable string with a max length of 20, and we use it to store the customer's order number for reference.
After adding my new SalesOrder and calling SaveChanges, I get the following error:
Cannot insert the value NULL into column 'OrderID', table 'SalesOrder'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Problem is, the object that I'm saving actually does have an OrderID! It's almost like it's trying to save the entity first before it saves all the values. Is this how EF handles things?
My setup is EF4.1, using an EDMX model-first approach. StoreGeneratedPattern is set to None. Default Value is currently set to (None) but I've tried various values. Entity Key is False, since it's not part of the key. I've also tried deleting the SalesOrder entity and regenerating it from the database.
I would also like to see your code...I had similar problems when filling objects in a loop then saving them with savechanges. I thought all the fields were populated, but they were not.
I'd have to see your code that executes before the save changes before I can offer anything really helpful.
If your problem is like mine and you are calling savechanges after using an iterator to populate your objects, then you can find the bad data by moving savechanges into the iterator so that it is called with each iteration...but this is all hypothetical guesswork without seeing your code...