ObjectContext update an object from a detached state - entity-framework

I have an ObjectContext with an update method. The method takes a generic object as a parameter. I need to attach this object to the ObjectContext and update the database with the changes the object had. example, I create a new object that has the same key as and entity in the database but some of the fields are different. I want to attach the object to its corresponding entity in the database and have it save the changes the new object has. Here is what i have in the Update method:
public void Update(BaseObject data, entitySetName)
{
AttachTo(entitySetName, data);
Refresh(RefreshMode.ClientWins, data);
SaveChanges();
}
After the refresh, the data get overwritten by the fields from the database. Leaving out the refresh also does not update the database record. Am I missing a step?

The DetectChanges() method will update the entitystate to modified if any changes have been made.
From MSDN: "In POCO entities without change-tracking proxies, the state of the modified properties changes to Modified when the DetectChanges method is called. After the changes are saved, the object state changes to Unchanged."
context.DetectChanges();
Additionally you could just set the state to modified so your method always trys to update regardless of whether anything has changed or not with:
ObjectStateManager.ChangeObjectState(data, EntityState.Modified);

Use simply:
public void Update(BaseObject data, entitySetName)
{
AttachTo(entitySetName, data);
ObjectStateManager.ChangeObjectState(data, EntityState.Modified);
SaveChanges();
}

Related

How to update already tracked entity

Hello i have the following problem:
I am retrieving an entity using EF Core and then inside a transaction i try to update it.
The update throws exception if i try to change the entity state to MODIFIED AFTER i retrieve it from the database.
I understood later on that if i get the entity from the context, it is already tracked at that point, and all further updates do not need to imply changing the entity state.
Based on this assumption in the code below i have commented the state change.Unfortunately at the end the entity does not get updated.Even if i call SaveChanges.
public void SomeMethod(DbContext context)
{
var entity=this.context.Find([some entity]); // the entity is started to get tracked
using(var tran=this.context.BeginTransaction())
{
try
{
//do some modifications on entity
// entity.Field1="tt";
// entity.Field2="ttx";
//this.context(entity).State=State.Modified -> throws exception saying entity is already tracked
this.context.SaveChanges();
tran.Commit(); // entity is not updated in the database !
}catch
{
tran.Rollback();
}
}
}
P.S Besides this i have also tried to first change the entity state to Detached and then Modified.It still threw exception on the Modified line.
Could someone tell me how to perform an update on an already tracked entity?
Update
I have also tried without transaction, and still the tracked entity does not get changed.So this basically does not save changes:
var entity=this.context.Find([some entity]);
//do some changes on entity without changing the entity state
this.context.SaveChanges();
Update 2
Apparently the problem is from the updates.I am not just setting fields.
I am indeed somewhere creating a new entity.
The problem was due to the fact that i was instantiating a new entity in my code and this new entity was not tracked and ... i was expecting it the pop up in the database.
Once i changed to an entity that was being tracked , the update was succesful without requiring to change its state to Modified or otherwise.

Entity Framework Core updating unchanged fields

I'm not sure if this is a question about Entity Framework, or how the audit.net library works, but I was guessing it was with how I was performing updates with EF. My goal is to capture only actual changes to the record, but it's capturing everything as change, even if the old and new values are identical.
Basically to simplify it as much as possible, if I do
var existing = context.Appl.FirstOrDefault(a => a.Id == id);
context.Appl.Update(existing);
context.SaveChanges();
(Changing nothing)
The Audit.Net change log says every single field was changed, and looks like
"Changes": [
{
"ColumnName": "FOO",
"OriginalValue": "",
"NewValue": ""
},
..... many more
My goal is to capture only actual changes to the record
Then you should not use the Update method.
According to the Update method documentation:
Begins tracking the given entity in the Modified state such that it will be updated in the database when SaveChanges() is called.
All properties of the entity will be marked as modified. To mark only some properties as modified, use Attach(Object) to begin tracking the entity in the Unchanged state and then use the returned EntityEntry to mark the desired properties as modified.
The main usage case for Update method is to perform a so called forced update when working with Disconnected Entities. Since your existing entity is retrieved from the context (or in other words, is tracked by the context), hence all you need is to set the new values. Change tracker will detect if there are actual property changes and will issue UPDATE command with only modified values (or no UPDATE command at all if all current values are equal to the original values).

UnitofWork [aspnetboilerplate] Transaction Management

I am currently working on implementing aspnetboilerplate's transaction management
Below is the method I am using to insert a order and products associated with the order
public class OrderController
{
IOrderAppService _orderAppService;
public OrderController(IOrderAppService orderAppService)
{
_orderAppService = orderAppService;
}
public void TestOrder()
{
_orderAppService.TestTransaction();
}
}
public class OrderAppService : IOrderAppService
{
//repositories are injected here
public void TestTransaction()
{
//Created 'order' and 'products' here
//Committing the created objects
CommitOrderTransaction();
}
private void CommitOrderTransaction()
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
//Inserts the Order record
CommitInsertOrderHeader(); // Order Header is saved in database by using SaveChanges() method
//Inserts the Product records associated with OrderId
CommitInsertOrderDetails();
unitOfWork.Complete();
}
}
}
As the aspnetboilerplate documentation tells that,
"if current unit of work is transactional, all changes in the transaction are rolled back if an exception occurs, even saved changes."
In my case when an exception occurs on inserting the OrderDetails, I would like the header record to be rolled back as well but I still have the Order header record in database.
you don't need to handle transaction manually. ABP handles it for you! All application service methods are automatically set as UnitOfWork. It's an atomic operation. So if any exception occurs in the middle of transactions all the db operations are being rolled back.
further information check out https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work
If you are calling SaveChanges() twice and you aren't using a TransactionScope across both, then you won't be able to rollback the first call. I don't know what UnitOfWork is doing here, but if the DbContext you are working with isn't being used in that UoW, then nothing is going to happen. DbContext is technically its own Unit of Work already. You should be adding Orders and Order Details to the same DbContext and calling SaveChanges() just once. Then you'd be able to roll back both in that scenario.

Entity Framework 5 Foreign Key New Record on SaveChanges

I'm using .NET4.5/EF5 and have created the model from an existing database.
I'm using the following code:
Order currentOrder = new Order();
using (var db = new ILSEntities())
{
try
{
Event currentEvent = db.Events.OrderByDescending(u => u.EventID).FirstOrDefault();
currentOrder.Event = currentEvent;
db.Orders.Add(currentOrder);
db.SaveChanges();
And I'm seeing that a duplicate record is being created of the Event object I find, which is not what I wanted to happen.
I've read a lot of posts relating to similar problems, but where the context of the two participants in the foreign key relationships are different. Here, I'm saving with the same context I use to find one, and the other object is new.
I've also tried:
currentOrder.Event.EventID = currentEvent.EventID;
but that fails as well as I get an EF validation error telling me it needs values for the other members of the Event object.
I've also tried specifically setting the EntityState of the object being duplicated to Detached, Modified etc. after adding the Order object but before SaveChanges without success.
I'm sure this is a basic problem, but it's got me baffled
In my understanding, both parent and child objects have to be in the context before you assign any relationship between them to convince the entity framework that an entity exists in the database already. I guess you are trying to add new Order object to Database, to add new object you should be using AddObject method, Add() method is used to establish relation between entitties. In your code, currentOrder is not in the context. Try to hook it in the same context and then assign a relation. Your code should look like this :
Order currentOrder = new Order();
using (var db = new ILSEntities())
{
try
{
Event currentEvent = db.Events.OrderByDescending(u => u.EventID).FirstOrDefault();
db.Orders.Attach(currentOrder); //attach currentOrder to context as it was not loaded from the context
currentOrder.Events.Add(currentEvent);//establish relationship
db.ObjectStateManager.ChangeObjectState(currentOrder, EntityState.Added);
db.SaveChanges();
}
}
OK, I did in the end figure this out, and it was my fault.
The problem was that the Order object is FK'd into another table, Shipments, which is also FK'd into Events. The problem was that it was the Event reference in the Shipment object that was causing the new record. The solution was to let EF know about these relationships by adding them all within the same context.
The code assembling the object graph was spread over a number of webforms and the responses here made me take a step back and look at the whole thing critically so whilst no one of these answers is correct, I'm voting everybody who replied up

Entity framework and pure POCO update

How do I do an update on a pure POCO object using entity framework 4?
Lets say I change the person's first name and call the repository in this manner:
public User Update(User user)
{
//User originalUser = GetUser(user.UserId);
//Is there a way to update the values that are only changed?
context.Users.Attach(user);
context.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
return user;
}
I dont want null values to update the database to null. For eg. Suppose I have LastName as a property but when passing the object to the update function, it was null. Am I going to have to get the originalUser and then update each property accordingly?
"update each property accordingly?"
No, you can use,
context.ObjectStateManager.TryGetObjectStateEntry(newItem, out entity);
// this will gives you the entity present in db and after that I suggest to write your code to change the state and save.
Also suggest you to read this
for more info on tracking changes in POCO entities