I have a windows service that runs every 10 seconds ... each time it runs, it takes some test data, modifies it and persists it to the database using the EntityFramework. However, on every second run, when I try to persist the change I get the following Optimistic Concurrency Exception:-
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries
I know for a fact that there is nothing else writing to that DB but my service which updates records every 10 seconds. What could be causing the concurrency exception here ?
I think a related entity somewhere in the object graph was getting modified prior to the second save operation.
All i am doing really is instantiating a new object context, and calling a save operation on some records i had retrieved using the same context.
The following code worked ---
var ctx = new blahEntities();
var profile = ctx.ProfileSet.Where(pr=>pr.FirstName.Contains("a")).FirstOrDefault();
profile.Address = "modified";
ctx.SaveChanges();
ctx.Refresh(RefreshMode.StoreWins,profile);
The "unexpected number of rows (0)" indicates that more than likely you don't have an ID field correctly mapped or defined in your entity model, or you are modifying a detached entity and attempting to save it and it doesn't have key information.
Run SQL Server profiler, or Entity Framework Profiler, and see what is going on in the background.
Once had this same issue and spent hours tracking it down to a malfunctioning update trigger. If you have any triggers on the table that's being updated, make sure they're working correctly. I work in an Oracle environment, fwiw.
Related
working with Spring data JPA and reading it Hibernate first level cache is missed, the answer says "Hibernate does not cache queries and query results by default. The only thing the first level cache is used is when you call EntityManger.find() you will not see a SQL query executing. And the cache is used to avoid object creation if the entity is already loading."
So, if If get an entity not by its Id but other criteria, if I update some property I should not see an update sql inside a transactional methods because it has not been stored int the first level cache, right?
According to the above answer, if I get some list of entities, they will not be stored in first level cache not matter the criteria I use to find them, right?
When a Transactional(propagation= Propagation.NEVER) method loads the same entity by its id two times, is not supposed it will hit the database two times because each loading will run in its own "transaction" and will have its own persistent context? What is the expected behaviour in this case?
Thanks
So I'm hitting my webservice to save a row in the database if the id doesn't already exist. So I do this in two steps. First I run a select on the context to bring back the entity with the given id. If that returns null, I create a new entity and call saveChanges. This works perfectly almost always. However, when there are multiple requests hitting the webserver at the same time, there is a chance that 2 requests could run at pretty much the same time. When this happens, there is the chance that they both create a row. This is actually happening.
How would you handle this situation?
p.s. I'm using EntityFramework Core.
I am chasing an issue with MySql / EF Core where I randomly have an exception thrown saying Nested transactions are not supported. This exception does not occur when my system is only used by one user. But when I run my tests in parallel or when I have multiple users, the exception occurs. I looked at all the code and their is nothing that could create nested transactions.
The only piece of codes that scares me so far is something like the following:
using (var transaction = _context.Database.BeginTransaction())
{
// Create a few entities and add them to the EF context
...
// Insert the rows: hopefully at this point, my transaction is not commited yet.
_context.SaveChanges();
// I then want to update a few rows with a raw sql statement without
// having to load the entities in memory.
_context.Database.ExecuteSqlCommand("UPDATE ...");
// Now that I have inserted and inserted some data, I want to commit all these
// changes atomically.
transaction.Commit();
}
Is this safe? Am I guaranteed that my SaveChanges and ExecuteSqlCommand will be executed on the same MySqlConnection? I have the feeling that when I call SaveChanges, it closes my connection and puts it back on the connection pool. Then, my ExecuteSqlCommand takes a new connection from the pool (it may be the same one or another one). So my initial connection (the one where I opened the transaction) is put back in the pool and it could be reused by another thread.
This is just a hunch and I am totally not sure if this could cause the problem.
My real question in the end is:
is it safe to use SaveChanges and ExecuteSqlCommand within a transaction?
I upgraded from MySql.Data.EntityFrameworkCore/MySql.Data 6.10.1-beta to 6.10.3-rc and it looks like the problem is gone. Since the problem was random I can't be totally sure that the problem is indeed fixed, but so far so good.
EDIT:
3 years later, the problem was never observed anymore.
I need to make stock control, so I need to ensure that when I modified the amount of product, is doing in the right way. I am using Entity framework 4.0
For example, if I use a transaction, when I load the record from the database, the recored is blocked, so I can substract or add to the loaded amount, the number of items that I need. However, this block the record in the database and perhaps for performance reasons is not the best way. This makes me ask when to use transactions with EF.
The other option is to use the concurrency fixed of entity framework, using a timespan column to detect if the record has been changed. In this case, if the record has been modified between my load and my update, I get the exception of concurrency. But it could occur that in my exception handler, if I update my context with the database data, between my refresh and the savechanges could be changed again.
Other problem is I finally can save the changes. For example, I have 10 units, I need to substract 8 but between my load and my update, other person substract 5 units. If I subtract 8, then in stock I have -3 units. This is not possible. If I have a transaction, I load the record, is blocked, so I can check if I have enough units, if yes, I can subtrack, if not, I send an exception.
So my question is, I know that EF is a transaction by itself, but it exists also transactions in EF, so it would be useful in some cases. When to use EF and cocurrency fixed and when to use transactions?
Thanks.
Daimroc.
Transactions should not be used to solve concurrency. You should make transactions as short as possible to not block your databases. The way to go here is optimistic concurrency - in the database (SqlServer) you create a rowversion column that changes automatically each time a row is modified. You use it as concurrency token. When saving changes EF checks this against the value on the entity and if they don't match it throws an exception.
Note that for SaveChanges EF always creates a transaction since typically you save more than one entity and if something goes wrong the database needs to be reverted to the original state - otherwise it would be in a corrupt state.
To prevent from going below zero - if you use the optimistic concurrency - you won't be able to save if the value in the database changed since the concurrency token will be different because row was modified and therefore the check on the client should be sufficient. Alternatively you could map saving an entity to a stored procedure that will check the value before saving and would return an error if the value after saving would be incorrect.
I'm using MVC4 with Entity Framework 4.1.
Initially we have created an Ado.net entity model from database. In the .edmx file, some of the tables that are in the database are not visible as they dont posses the primary key on particular table.
As our project is moving forward, we need to update to one of the log tables which dont have a primary key field.
So, we modified our .edmx file instead of modifying in the database. our client asked us not to modify the database fields. we have modified the .edmx and created a pk on one of the exisiting field in the table(say tbl_log table).
we are trying to update the tbl_log. But it gives an error message as Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
I've seen much of questions in stack overflow and also googled a bit, but could not find any solution.
Even i've tried refreshing the ObjectStateManager entries but it still points to the same error.
Here is my code
tbl_log log = new tbl_log();
Entity.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Modified);
log.LoginId = strLoginId;
log.Password = strPassword;
log.IPAddress = strIpAddress;
log.Date_Time = DateTime.Parse(DateTime.Now.ToString());
log.sessionId = new Guid(strSessionId);
Entity.AddTotbl_log(log);
Entity.SaveChanges();// optimistic concurrency error
Please help
Thanks,
Karthik
Your model must represent the database schema. If you add a PK to the model it should exist in the database as well, otherwise you will get errors. It's generally bad practice to not have a PK on any table, even if the table is an audit log table.
What the exception is telling you is that the object tracker cannot determine if the state of the object has changed since the last call to the database. This is because the PK you have set is still 0 even after the framework has sent the insert/update query.
Unfortunately there is no good way to work around this. I would suggest (as I think Microsoft does) to add a primary key column to every table in your database.
EDIT - From comments
As the PK is used to track the object, if you have set the PK to have a StoreGenerationPattern of Identity in your model it will be expecting the value to change. When it doesn't change then it will throw the error your are seeing. Try changing the StoreGenerationPattern to None as then EF won't be expecting your faux-PK to change