I have a detached set of client objects that I'd like to update (I know they already exist in the db by primary key). Now I want to update them to the database. Knowing I need to query them first, I do so and now have to basically take the properties from the deattached objects and apply them to the attached objects. I finally call save changes. Is there a slick way to apply these properties from the detached collection to the attached one?
NOTE: The detached objects don't have the primary keys in them but I do have enough information to link with via a comparer class.
You don't need to do what you're doing. You can just call the Attach method on your ObjectContext to tell it that you want to work with your detatched objects. Then just call SaveChanges to update the database with your changed objects.
Related
I'm trying to do a copy of an object in ef-core 2.0. Im using a query that fetches a lot of objects with Include ande then I use the AsNoTracking to tell ef that this is a completly new object.
Im using the default settings and I'm letting the database generate the Ids on insert. But when I use the AsNoTracking-query I still get the id of the original object which gives me an exception on SaveChanges.
SqlException: Cannot insert explicit value for identity column in table 'Plans' when IDENTITY_INSERT is set to OFF.
I dont actually want to change this setting and if i traverse the objects and changes the Id to 0 it works. Is there any way to handle this problem without traversing all the objects?
Is there a better way to do create a copy?
As Ivan comments above there is no better answer than that so check this link out for a better answer. In my case I get the object and the hierarchy in the same way as before then traverse the objects and sets the PK to 0.
Replicate Entire Row In Entity Framework Core
I have several entities that contain datetime fields for EffectiveAsOf and ExpiredAsOf. When an entity is modified I want to override the SaveChanges method and rather than just update the existing entity have the code save the original record back to the database with an ExpiredAsOf datetime set to the current time, and a new record inserted with the new data and EffectiveAsOf set to the current time with ExpiredAsOf set to null.
I know that the ObjectStateEntry items in the objectStateEntryList contain CurrentValues and Original values objects, as well as an Entity object. What does EF use to write data to the DB the CurrentValues data or the Entity? How do I go about creating a new entry? Or, am I going about this the wrong way entirely?
I know that I can handle this in the entities outside of EF, but would rather have EF detect and handle these entities automatically.
Thanks in advance for your help and insight,
Jim
EF by default will use both - it uses original values to check for a concurrency issue (i.e. if the record has changed since you loaded the data from the DB) then uses the entity's current/modified values to update the DB record.
It is not possible to have EF "detect and handle these entities automatically". You will need to create a new instance of the entity object, copy the values from the existing entity object, set the appropriate effective and expired dates on both objects, add the new entity object to the DbContext, then save changes. The best place to do this is by overriding the SaveChanges() method of your DbContext. To keep it as clean and manageable as possible, I suggest using the repository pattern.
We're creating a WebAPI using Entity Framework in MVC 4. Our client wants to send complex objects containing related objects - both new and updated. The root object maybe new or existing one too. The client generates primary keys - we're using Guids for that. So on server we really can't tell that we got an existing object update or a new one. What would be the best way to handle this situation? We need some sort of add or update functionality and it's not yet clear to us how to proceed with Entity Framework for this.
EF doesn't have any build in support for discovering changes in detached object graph. You either have to include some field into every object describing if the object is new, not modified, updated or deleted (you will also need similar behavior to track changes in many-to-many relationships). If you don't use such field you have no other way than querying database and comparing current DB state with data received from client to find what has changed.
I need to copy data from one database to another with EF. E.g. I have the following table relations: Forms->FormVersions->FormLayouts... We have different forms in both databases and we want to collect them to one DB. Basically I want to load Form object recursively from one DB and save it to another DB with all his references. Also I need to change IDs of the object and related objects if there are exists objects with the same ID in the second database.
Until now I have following code:
Form form = null;
using (var context = new FormEntities())
{
form = (from f in context.Forms
join fv in context.FormVersions on f.ID equals fv.FormID
where f.ID == 56
select f).First();
}
var context1 = new FormEntities("name=FormEntities1");
context1.AddObject("Forms", form);
context1.SaveChanges();
I'm receiving the error: "The EntityKey property can only be set when the current value of the property is null."
Can you help with implementation?
The simplest solution would be create copy of your Form (new object) and add that new object. Otherwise you can try:
Call context.Detach(form)
Set form's EntityKey to null
Call context1.AddObject(form)
I would first second E.J.'s answer. Assuming though that you are going to use Entity Framework, one of the main problem areas that you will face is relationship management. Your code should use the Include method to ensure that related objects are included in the results of a select operation. The join that you have will not have this effect.
http://msdn.microsoft.com/en-us/library/bb738708.aspx
Further, detaching an object will not automatically detach the related objects. You can detach them in the same way however the problem here is that as each object is detached, the relationships that it held to other objects within the context are broken.
Manually restoring the relationships may be an option for you however it may be worthwhile looking at EntityGraph. This framework allows you to define object graphs and then perform operations such as detach upon them. The entire graph is detached in a single operation with its relationships intact.
My experience with this framework has been in relation to RIA Services and Silverlight however I believe that these operations are also supported in .Net.
http://riaservicescontrib.codeplex.com/wikipage?title=EntityGraphs
Edit1: I just checked the EntityGraph docs and see that DetachEntityGraph is in the RIA specific layer which unfortunately rules it out as an option for you.
Edit2: Alex Jame's answer to the following question is a solution to your problem. Don't load the objects into the context to begin with - use the notracking option. That way you don't need to detach them which is what causes the problem.
Entity Framework - Detach and keep related object graph
If you are only doing a few records, Ladislav's suggestion will probably work, but if you are moving lots of data, you should/could consider doing this move in a stored procedure. The entire operation can be done at the server, with no need to move objects from the db server, to your front end and then back again. A single SP call would do it all.
The performance will be a lot better which may or may not not matter in your case.
I have a problem when I add an entity object with ObjectContext.AddObject method because I can't retrieve that object with LINQ querying my ObjectContext.Person entities. I know that this new added object is stored somewhere, because it is used to update database after SaveChanges method. That's bothers me because I want to update my datagrid DataContext without saving changes unless I really want to do it. It doesn't help if I add the same object to DataContext list myself directly. Also, when I call DeleteObject method it just marks object for deleting but I have to find it an remove it from DataGrid and retrieve if I cancel changes.
If you add an object to your ObjectContext and want to retrieve it without querying the database, you can use ObjectContext.GetObjectByKey.
Your second question is unclear to me.