I am working on asp.net mvc with EF codefirst. I am trying to update the list of records at once. like,
foreach(var pat in listpats)
{
context.Entry<Patient>(pat).state=EntityState.Modified;
context.savechanges();
}
and its working fine for me. Now suppose if listpats contains 10 items, if i got exception at 7th item while i am updating. it will save first 6 items. but i want to save all records at once if no error occurred while updating. if any error occurred mean while i should rollback all the previous changes. so how could i achieve this using EF code first model. please guide me.
You should invoke SaveChanges() outside foreach:
foreach(var pat in listpats)
{
context.Entry<Patient>(pat).state=EntityState.Modified;
}
context.SaveChanges();
This way if an exception occurs everything will be rolled back
If you've modified the entities in some other code then their state will be modified (within the same context) without you having to explicitly change it with a foreach loop and context.Entry(pat).state=EntityState.Modified.
So taking a step back, after you've modified all your patients entities a single call to context.SaveChanges() will automagically rollback on error.
Soooo to summarise, change all the patients entities and afterwards call context.SaveChanges() which will make EF propogate all the entities that have a modified state (the state change happens when you modify the entity) to the DB, context.SaveChanges() will handle simple cases like this with regards to rollback.
P.S. Your question is making me wonder if you've changed the patients in a different context and that's why your manually changing the current context' state.
Related
I have an entity like this:
EntityA {id, someCollectionOfEntityB}
I load entityA from server with an expand on someCollectionOfEntityB.
I have one item in the collection.
Then on the server-side this item is deleted from DB by some third-party application.
Later my client application makes another call to fetch EntityA with an expand. This time the expand finds no records and therefore the collection is empty.
Yet, on the client-side, the item that was deleted from DB is still in the collection.
Why ? And how do I change this behaviour ?
[EDIT]
I have used the following strategy, but it does not solve the problem:
query.queryOptions = new breeze.QueryOptions({ mergeStrategy: breeze.MergeStrategy.OverwriteChanges });
In the end, I'm looping through the entities in the collection and I detach each one of them before querying the server again.
I don't think this is a very neat way to solve this issue. So I'd love to hear from the breeze team on this matter :)
Im talking about asp.net mvc
so basically an instance of the dbcontext gets initialized, puts the data in the view then it gets disposed of.
how does it track changes made to the entity if the "entry" which contains the original and present value get ...well disposed of.
Well, it doesn't.
Let's say you fetch an entity from the database for an edit view. Then the edit view is generated from the entity. Now the context is disposed, as it is not needed anymore. We have all the data needed to create view. Context doesn't track any changes you do in the view and when you think about it, how could it anyway?
Now you post the edit view. Context has no idea that the model has been changed. On the edit action method you mark the posted entity as dirty with db.Entry(entity).State = EntityState.Modified that doesn't do anything yet really, but when you call db.SaveChanges all the dirty entities are updated, added or deleted. After this the context is disposed again.
The point is EF doesn't track the changes for you, it's you who decides which entities are being updated. It updates the entity yes, but it doesn't know what has been changed since the last update (atleast I think so, why would it need to track the changes?).
I'm using Entity Framework (DbContext with database first) with MVC. When user save from a form, I have a condition in the controller that send the entity to the update of insert method depending of some internal flag of mine.
When sending entity to the update method, I flag it to modified using context.Entry(myEntity).State = EntityState.Modified;, I call saveChanges() and everything work well.
When sending the entity to the insert method, I flag it to added using context.Entry(myEntity).State = EntityState.Added; but when calling saveChanges() I receive error about 2 fields that are required...
The problem is that thoses 2 fields are not empty and they effectively contain valid data just before saving... I have even try to force new values to thoses 2 fields just before saving but same error.
It may be usefull to mention that I'm using Devart DotConnect For PostgreSQL as db provider.
Any idea how to debug this problem?
EDIT:
Here is the error:
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
When looking for this EntityValidationErrors I receive the 2 following specific errors:
The flg_actif field is required
The user_creation field is required
As mentionned before, those fields are filled with data just before saving so I don't understand what is happening.
I'm using EF v4.0.30319 (system.data.entity=> v4.0 and EntityFramework=> v4.4)
EDIT2:
Just to clarify a little bit more: The entity I'm trying to insert already exist in database. The form show the data of this database row. When saving, I decide if I update the row (this work well) but sometime, I need to insert the edited row as a new register instead of updating it to keep an history of the change in database.
Could you verify if the EntityKey property is set or null on the items you are trying to save?
If it already has a key, the context is already aware of the item, and you should use Attach instead of setting the state to added manually.
EDIT: To summarise the point from below. It looks like what you are doing is inserting a new copy of a row already associated with a context. That is almost certainly your problem. Try creating a fresh object based on your original row (i.e. copy the variable values or use a copy constructor), then add that new object.
Additionally, you should not need to set the state manually on a newly added object. You are trying to force the state here because the context doesn't see that item as a new one.
I'm having an issue updating an entity with multiple related entities. I've got a very simple model which consists of an article entity and a list of categories the article can be related to. You can choose from a check box list which of these categories are associated to it...which works fine.
The problem crops up when I actually come to update an existing entity using the dbContext. As I am updating this entity, I have already detached it from the context ready to re-attach it later so the update can execute properly.
I can see that after I posting the model, the category(s) are being added to the article entity just fine and it looks like it updates in the repository with no errors occurring.
When I look in the database the article has updated as normal but the category(s) have not.
Here is my (simplified) update code...
public virtual bool Attach(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
_dbSet.Attach(entity);
return this.Commit();
}
Any help will be much appreciated.
Ok I understand what I was doing wrong now. I was using the following to select the entity from the context to model bind before it hits the controller action.
T entity = _dbSet.Find(id);
_dbContext.Entry(T).State = EntityState.Detached;
return entity;
Instead of...
return _dbSet.AsNoTracking().FirstOrDefault(predicate);
By detaching the entity, none of the navigation properties are loaded and therefore no changes can be made against them. Using AsNoTracking() still loads the navigation properties but also allows the entity object to be attached back for an update.
Hope this helps someone else in a similar situation.
I have an oData generated DataServiceContext and I am successfully adding entities to it. I need to add a whole load of entities and then commit them in a single SaveChanges with the Batch option set at the end. This is all fine, until I come to query it before the save changes.
Outline is:
Create a new entity
Add it to the DataServiceContext
Run a query on the context looking for the item I have just added - IT IS NOT FOUND
My previous work with EF4 would suggest that if this was an Entity Context, all would be fine, but because this is a Service Context I cannot query for an entity that has been added but not saved to the service.
Is this the case?
DataServiceContext is basically just a small helper. Running any query against it will run the query on the server directly, the client will not try to fixup the data in any way. Since you're changes haven't made it to the server yet (SaveChanges was not called yet), the query will not return the newly added entities.
If you really need to list the entities you've added before SaveChanges, you could use the DataServiceContext.Entities collection which will return EntityDescriptor for all entities tracked by the context. You can list those added by looking for those with state Added.