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.
Related
I am creating an application which uses WCF (4.5), EF (6.1), Unity (3.5) and Unity3.Wcf (3.5)
The application needs to run a monthly process which checks for changes that have happened in last month and create a record for an approval process.
This process will be triggered by a call to a WCF service method.
This is the basic logic:
Get collection of Things
For each Thing:
Get collection of ThingChanges
Calculate changed Amount
Create New ThingApproval
Update each ThingChange in ThingChanges with ThingApproval.ID
Now, as far as I am aware, in order to get ThingApproval.ID, I need to do SaveChanges after Create New ThingApproval which will populate with the ID from the DB. I then need to do a further SaveChanges either after each Update or once after the for each completes to commit all the updates.
If any part of this process fails, it needs to rollback ALL changes, back to before the first SaveChanges
How can I implement this?
I ended up implementing the GNaP.Data.Scope.EntityFramework package which gives full control of the DB Context, including transactional.
Not sure why this just started happening, but I have a situation where an entity I am reading from the database doesnt contain the new values that were updated from a stored procedure before. I see the changes in the database after my stored procedure makes the update, and I also call UnitOfWork.Commit to save any other changes. I think make a call to get this item again, and the values are not the same as the ones in the database. Any reason for this? I am not grabbing this item anywhere before the update so I dont know how EF knows about it the first time I grab it after the update.
I'm going to guess Entity Framework is caching those values somehow. I would try using the Refresh() method to force Entity Framework to go back to the data store with RefreshMode.StoreWins to ensure the data store values win.
I moved some logic around so the item is updated before any EF calls.
I'm using Entity Framework 4.1 and have a seemingly simple requirement: I want to either get an entity by a unique key, or if it doesn't already exist, create it:
var user = db.Users.SingleOrDefault(u => u.Sid == sid);
if (user != null)
return user;
user = new User(sid);
db.Users.Add(user);
Normally this works fine, but when I run a bunch of tests together (using MSTest) one of them consistently fails with "Sequence contains more than one element". When I run that test by itself it works fine.
The problem seems obvious: multiple threads are calling the above code concurrently and each create a new User row. But what is the solution?
The proper solution is a transaction, of course, but I just cannot get it to work. EF won't use a normal DbTransaction if I start one. If I use a TransactionScope it either has no effect (the same error occurs) or EF tries and fails to start a distributed transaction, even if I follow the advice about opening a connection first.
This is really frustrating, because it is such a trivial thing to do with plain old SQL: begin transaction, SELECT, INSERT, commit transaction. How can I get this to work in EF? It doesn't have to be using transactions - whatever makes it work.
The first statement (the only one which could cause the error you describe) will never fail if your DB has a UNIQUE constraint on Sid. Does it? It should. That's the only way to make sure that the sid is truly, globally unique.
I'd like to know what is the best practice to track and/or persist changes over time if I use EF. I'd like to get started with EF for a new project. What I need is a kind of change history.
That's how I did it before: If a record was created it was saved with an ID and with the same ID as InvariantID. If the record was updated i marked it as deleted and created a new record with the new values and a new ID but the same InvariantID. Like this I always had my current record but a history of changes as well.
This works perfectly fine for my scenarios. The amount of historical records is not an issue because I use this usually only for data that's not changing very often.
Is this build in EF somehow or what's the best way to get this behavior for EF?
No it is not build into EF and it will not work this way. I even don't think that it is a good approach on the database level because it makes referential integrity very complex.
With EF this will work only if you use following approach:
You will use conditional mapping for your entity - condition will be IsDeleted = 0. It will ensure that only non deleted entities will be used in queries.
You will have mapped stored procedure for delete operation to correctly set IsDeleted = 1 instead of really deleting the record
You will have to manually call DeleteObject to delete your record and after that you will insert new record - the reason is that EF is not able to deal with scenario where entity change its PK value during update.
Your entities will not be able to participate in relations unless you manually rebuild referential integrity with some other stored procedure
You will need stored procedure to query historical (deleted) records
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.