Entity Framework - add or subtract set amount from DB field - entity-framework

I am working on my first project using an ORM (currently using Entiry Framework, although that's not set in stone) and am unsure what is the best practice when I need to add or subtract a given amount from a database field, when I am not interested in the new value and I know the field in question is frequently updated, so concurrency conflicts are a concern.
For example, in a retail system where I am recording a sale, as well as creating records for the sale and each of the line items, I need to update the quantity on hand of the items sold. It seems unnecessary to query the database for the existing quantity on hand, just so that I can populate the entity model before saving the updated quantity - and in the time taken for that round-trip, there is a chance that the same item will have been sold through another checkout or the website, so I either have a conflict or (if using a transaction) the other sale is blocked until I complete my update.
In SQL I would simply write
UPDATE Item SET Quantity=Quantity-1 WHERE ...
It seems the best option in this case is to fall back to ADO.NET + stored procedure for this one update, but is there a better way within Entity Framework?

You're right. ORMs are specialized in tracking changes to each individual entity, and applying those changes to the DB individually. Some ORMs support sending thechanges in btaches, but, even so, to modify all the records in a table implies reading them all, modifyng each one, and sending the changes back to the DB as individual UPDATEs.
And that's a big no-no! as you have corectly thought. It implies loading all the rows into memory, modifying all of them, track their changes, and send them back to the DB as indivudal updates, which is way more expensive that running a single UPDATE on the DB.
As to the final question, to run a SQL command you don't need to use traditional ADO.NET. You can run SQL queries directly from an EF DbContext using ExecuteSqlCommand like this:
MyDbContext.Database.ExecuteSqlCommand('Your SQL here!!');
I recommend you to look at the MSDN docs for Database class, to learn all the things that can be done, for example managing transactions, executing commands that return no data (as the previous example) or executing queries that return data, and even mapping them to entities (classes) in your model: SqlQuery().
So you can run SQL commands and queries without using a different technology.

Related

Is optimistic locking equivalent to Select For Update?

It is my first time using EF Core and DDD concepts. Our database is Microsoft SQL Server. We use optimistic concurrency based on the RowVersion for user requests. This handles concurrent read and writes by users.
With the DDD paradigma user changes are not written directly to the database nor is the logic handled in database with a stored procedure. It is a three step process:
get aggregate from repository that pulls it from the database
update aggregate through domain commands that implement business logic
save aggregate back to repository that writes it to the database
The separation of read and write in the application logic can lead again to race conditions between parallel commands.
Since the time between read and write in the backend is normally fairly short, those race conditions can be handled with optimistic and also pessimistic locking.
To my understanding optimistic concurrency using RowVersion is sufficient for lost update problem, but not for write skew as is shown in Martin Kleppmann's book "Designing Data-Intensive Applications". This would require locking the read records.
To prevent write skew a common solution is to lock the records in step 1 with FOR UPDATE or in SQL Server with the hints UPDLOCK and HOLDLOCK.
EF Core does neither support FOR UPDATE nor SQL Server's WITH.
If I'm not able to lock records with EF Core does it mean there is no way to prevent write skew except using Raw SQL or Stored Procedures?
If I use RowVersion, I first check the RowVersion after getting the aggregate from the database. If it doesn't match I can fail fast. If it matches it is checked through EF Core in step 3 when updating the database. Is this pattern sufficient to eliminate all race conditions except write skew?
Since the write skew race condition occurs when read and write is on different records, it seems that there can always be a transaction added maybe later during development that makes a decision on a read. In a complex system I would not feel safe if it is not just simple CRUD access. Is there another solution when using EF Core to prevent write skew without locking records for update?
If you tell EF Core about the RowVersion attribute, it will use it in any update statement. BUT you have to be careful to preserve the RowVersion value from your data retrieval. The usual work pattern would retrieve the data, the user potentially edits the data, and then the user saves the data. When the user saves the data, you would normally have EF retrieve the entity, update the entity with the user's changes, and save the updates. EF uses the RowVersion in a Where clause to ensure nothing has changed since you read the data. This is the tricky part- you want to make sure the RowVersion is still the same as your initial data retrieval, not the second retrieval used to update the entity before saving.

batch updates using Entity Framework

Can anyone suggest me how to deal with batch updates using Entity Framework?
For ex: Updating a field for a list (List) of between 100 and 1000 Id's, which the primary key. Calling each update separately seem to be to much overhead and takes a long time.
Until you call SaveChanges() none of the data is updated in the database so you can make how many changes you'd like.
You can take a look at a Unit of Work design pattern if you want a more structured way of saving changes to the database.

Entity Framework Self Tracking Entities - Synchronize between 2 databases

I am using Self Tracking Entities with the Entity Framework 4. I have 2 databases, with the exact same schema. However, tables in one database will be added to/edited etc (and I mean data will be added/edited, not the actual table definitions) and at certain points of the day I will need to synchronize all the changes between this database and the other database.
I can create a separate context for both of them. But if I read a large graph from one database, how can I update the other database with the graph? Is there an easy way?
My database model is large and complex and fully relational. So it would be a big job to go through every single entity and do a read from the other database to see if it exists or not, update/insert it if need be, and then carry this on through the full object graph!
Any ideas?
This is not a use case for EF. In EF you will have to do exactly what you've described. Self tracking entities are able to track changes to these object instances - they know nothing about changes made to their own database over time and they will not know anything about state of your second database as well.
Try to look at SQL server native features (including mirroring, transaction log shipping or SSIS) and MS Sync framework. Depending on your detailed requirements these tools can suite you better.

What are the differences in EF when using your own Insert, Update and Delete Functions?

I am looking into adding history tables to my database. The easiest way is to intercept all Insert, Update and Delete calls that EF Makes and add in a merge that will also insert a history row into a history table.
Right now all my Entities just let EF figure out how to do the inserts, updates and deletes.
If I go and add in stored procedures (instead of the EF Generated stuff) will EF still function the same on the business tier?
Or does it change how I have to work with my entities? If so, how?
Everything works the same, it is transparent.
Stored procedures need to return the rows affected, in order for EF to know that the update succeeded or not. Additionally, if you do an update and need to map any property back to your entity (e.g. timestamps) you must select them in the sproc and then map them back in the EF designer (since you can only have one output parameter, and that should be the rows affected).
You might consider using triggers on the DB to solve your issue, though?
Doing this in stored procedures means that you will write all inserts, updates and deletes yourselves. It is like throwing 30% of feature set (and 50% productivity) away. Create audit records in your application and save them together with main records through EF.

Syncing Core Data Databases in iOS applications

I have a doubt about Core Data migration.
Say I have an application which has some predefined values in a table A. I want to sync it with another database, with a table B in such a way that when new records are added totable B, that record should get added to my table A.
I know using Core Data migration, when I add columns to a table, I will be able to access the values previously stored in the older table before the addition of the column.
I would like to know how my table can be updated with the added records on another table.
Update:
From comment below:
The question I had in mind is this...
I want to release an update for my
app. I'm stuck on how to update the
existing Core Data database which also
stores data entered by the user. All I
need to do is update a couple of
records and preserve current user
data. How do I do this?
Core Data is not SQL. Entities are not tables. Objects are not rows. Columns are not attributes. Core Data is an object graph management system that may or may not persist the object graph and may or may not use SQL far behind the scenes to do so. Trying to think of Core Data in SQL terms will cause you to completely misunderstand Core Data and result in much grief and wasted time.
That way lies madness.
It sounds like you don't actually want to migrate as the term is used in Core Data. Migration in Core Data means moving from an earlier version of a data graph's persistent store to a newer version of the same.
E.g. In the 1.0 version you have an entity Person with the attributes firstNameand lastName. After the app has been release you wish to update to the 2.0 version and add a phoneNumber attribute to the Person entity. You would use migration to update the user's existing object graphs and persistent stores to the new object graph.
If by "table" you actually mean entities, then you can link entities together in a relationship so that they can watch each other. If by "table" you mean a data model or persistent store, then the answer is more complex. It can be done using configurations, fetched attributes, UUIDs etc but you must understand what you really need to do before you jump through all those hoops.