Save disconnected object in entity framework 4 - entity-framework

in EF1, i couldn't just update an object that was constructed (with the right id) outside the scope of the ObjectContext.
Is there a new way in EF4?
Can i just add it to the context (context.AddOrder(order)) (where context is an instance of my ObjectContext) and 'it' sees that it has an id and updates it?
It's non-poco so my objects derive from EntityObject

If it's a brand new object then you should use either ObjectContext.AddObject or ObjectSet.AddObject:
The AddObject method is for adding newly created objects that do not exist in the database. The entity will get an automatically generated temporary EntityKey and its
EntityState will be set to Added.
On the other hand ObjectContext.Attach and ObjectSet.Attach is used for entities that already exist in the database. Rather than setting the EntityState to Added, Attach results in an Unchanged EntityState, which means it has not changed since it was attached to the context. Objects that you are attaching are assumed to exist in the database.
For a more detailed discussion on this topic, please take a look at this post:
Entity Framework 4 - AddObject vs Attach

Use the Attach method instead. It is designed for disconnected objects.

Taken from Employee Info Starter Kit, you can consider the code snippet as below:
public void UpdateEmployee(Employee updatedEmployee)
{
//attaching and making ready for parsistance
if (updatedEmployee.EntityState == EntityState.Detached)
_DatabaseContext.Employees.Attach(updatedEmployee);
_DatabaseContext.ObjectStateManager.ChangeObjectState(updatedEmployee, System.Data.EntityState.Modified);
_DatabaseContext.SaveChanges();
}

Related

Insert List of Objects using Entity Framework

Hi i am trying to attach multiple objects in ObjectContextManager and try to set their state in "Added" Mode. These objects have some navigational properties with them and when i try to attach any object after attaching the first object. It throws me the error
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
The reason seems to be very obvious but what will be its solution.
Kindly guide
By calling Attach or AddObject on the entity you are actually attaching or adding whole object graph (EF traverse navigation properties and executes the operation on every related property). When you try to add or attach entity which was already attached or added as part of object graph you will get this exception. The solution is to understand your data model and call AddObject or Attach only for disjointed object graphs.
You should initialize the Id of new entities you add/attach with a random Id (like Guid.NewGuid().GetHashCode() if you use Int32 as Id-type)
Otherwise have all entities the default Id of 0, and so will the ObjectStateManager throw an exception when you attach the entities.

EF 4: Problems understanding DetectChanges when using POCO (no self tracking ObjectContext)

I wonder if anyone can help me?
I am having problems understanding why i need to issues DetectChanges on my POCO (non proxy) entities.
Of course i have this line to ensure that proxies are not returned.
context.ObjectStateManager.GetObjectStateEntry(order).State
And doing some research it appears if i need to check the "state" of an object then i need to issue detechChanges But why would i need to check the State of an object?
Basically I send along my POCO entity to a method that SAVES the data to a new ObjectContext (I create and destroy ObjectContext on each method)
Hence, i am having problems understanding why i would need to have ObjectContext track or be aware of changes?
Is it because that if its not aware if will not be saved?
Maybe i am miss informed but it appears that if i am using an existing ObjectContext (which i am not i am creating and destroying each time) that ensure ObjectContext is aware would be beneficial but otherwise not?
So in 1 method I am updating an object by creating a new datacontext, saving it to the db and destroying ObjectContext . Hence i am not using 2 methods, 1 method to send the update or new record and then another method for SAVING.
I would really appreciate any quick explaanations of why its needed?
Thanks in advance
Your question is little bit confusing. You are writting about Entity Framework but using DataContext which is related to LinqToSql.
The behavior differs in the way you are using ObjectContext. When you load POCO entity from database ObjectContext holds its instance in internal Identity Map. By default POCO doesn't use any kind of change tracking. When you save that POCO entity to the same instance of ObjectContext it internally calls DetectChanges to compare current entity state with stored state. This comparision defines which columns have to be updated. Internal call to DetectChanges is default behavior which can be turned off so you will have to call this method manually.
In your scenario you not using the same instance of ObjectContext. In that case you first have to Attach POCO entity to the ObjectContext. MSDN strictly says that when attaching entity it is marked as Unchanged. For that reason you have to say ObjectContext that entity has changed. You can do that for whole entity or you can define exactly which properties have changed but you have to do it manually = you have to store that information somewhere (Self tracking entities can help you with that but they have ohter disadvantages).

Is the activerecord pattern built into Entity Framework 4.0?

In the past I used Sub Sonic which has the activerecord pattern baked into the framework. With Sub Sonic it was very easy to find the "dirty" fields on an update. I now have a need to create an audit table in my application that utilizes Entity Framework 4. Is there a comparable feature in EF 4 that will give me the dirty fields?
Thanks for your help!
You can get similar functionality with what is described in this page at MSDN:
Identity Resolution, State Management, and Change Tracking
Change Tracking -> Change tracking
information for the object graph is
stored in ObjectStateEntry objects,
which are created by the ObjectContext
for each attached object.
ObjectStateEntry objects store the
following information for the
entities:
...
The names of the entity's modified
properties.
Entity State -> The object context must know the state of an object to
save changes back to the data source.
ObjectStateEntry objects store
EntityState information. The
SaveChanges methods of the
ObjectContext process entities that
are attached to the context and update
the data source depending on the
EntityState of each object. For more
information, see Creating, Adding,
Modifying, and Deleting Objects. The
following table shows the possible
states of an object.
The state of objects inside an object context is managed by the ObjectStateManager. To find out the state of an object, call one of the following ObjectStateManager methods: TryGetObjectStateEntry, GetObjectStateEntry, or GetObjectStateEntries. The State property of the ObjectStateEntry defines the state of the object.
Take a look at this article for more info:
What's New and Cool in Entity Framework 4.0

Moving entities between contexts in .NET Entity Framework 3.5

I've got a scenario in which I want to move a bunch of object graphs
between contexts. Specifically, I'm trying to import the contents of
one database into another. The there is a context [CurrentContext]
connected to the primary DB, and another context [ImportContext]
connected to another DB. I'd like to copy the entities from
ImportContext into CurrentContext, either inserting new records or
updating the existing records.
Something like this.
ImportContext.Organization.MergeOption = MergeOption.NoTracking;
foreach(var org in ImportContext.Organizations.ToList())
{
CurrentContext.Attach(org); // or
CurrentContext.AddToOrganization(org);
}
When I try the Attach method, the entity isn't saved because the
entitystate is Unchanged, and I can't figure out how to mark it as
new. Also, it appears Attach doesn't work if the entity is new,
because the EntityKey is tied to ImportContext.
If I set the EntityKey to null, I lose the associations between the
Organization and other entities.
AddToOrganization has the same problem with losing the associations,
or would fail if the Organization was once already in the
CurrentContext.
What's the appropriate approach to doing this type of importing? I'm
currently using EF3.5 and can't update the project to EF4.
Detach the entity from the old context.
AddObject the entity into the new context.

Unable to attach a detached entity: "An object with the same key already exists in the ObjectStateManager"

I am trying to attach an entity to the ObjectContext.
When I do so, the following InvalidOperationException is thrown:
An object with the same key already exists in the ObjectStateManager.
The ObjectStateManager cannot track multiple objects with the same key.
I checked in the object state manager and the item does not exist:
//Data context is actually the object context.
ObjectStateEntry contact;
while ( //Should only work once since it should be true if the item was attached
!DataContext.ObjectStateManager.
TryGetObjectStateEntry(Contact, out contact)
)
DataContext.Attach(Contact); //Here is the exception thrown.
Or look at this abstract example and tell me if it makes sense:
EntityState state = Contact.EntityState; //Detached
DataContext.Attach(Contact); //Throws the exception.
DataContext.AttachTo("Entities.Contacts", Contact); //Throws the Exception
var detached = DataContext.ObjectStateManager.
GetObjectStateEntries(EntityState.Detached);
//InvalidArgumentException - detached entities cannot be in the obj state mgr
Answers in VB are welcomed too.
Could your Contact entity have two child entities with the same EntityKey? For example, is it possible to get from the Contact entity to two Address entities with the same key?
If you specify MergeOptions.NoTracking a context will happily return a detached object graph that contains entities with the same key. However, when you attach the same object graph a System.InvalidOperationException will be thrown.
I would suggest that you look at the entire object graph that you are attaching to the context and check if there are objects with duplicate keys in it.
Answer is (and I didn't mention that this was the problem, since I didn't know it is), that if you set a navigation property to a tracked entity the new entity is automatically added:
Dim s = context.States.FirstOrDefault()
Dim a As New Address
a.State = s
Dim state = a.EntityState '= Added
Since I didn't know that I kept on wondering how come the entity is tracked.
I would delete the entire quesion but since there is effort of other answer that might be helpful I will leave it here, vote to close if you think it should be closed.
I had experienced the same problem within my application.
I have solved the problem by using ObjectStateManager TryGetObjectStateEntry Method
In fact the EntityState property is misleading developers. Although it is displaying Detached, interesting that causing error.
Check whether you are setting the EntityKey property of Entity object. If you are setting it, Make sure you are not copying from an existing entity object.