I am currently using LINQ and the Entity Framework to do my database connection layer. In my database I have a Files table and a Products table. I also have a ProductHasFiles table that joins the 2 in a many to many relationship.
My issue is this. I have a single file loaded in my context and I have a list of Product IDs that I need to either attach or detach from to the file record. How do I do that?
I know I can get all of the current Products attached to the File by doing File.Product.Load(); but how do I detach them once I do this? Also, is there a way to attach existing Products without loading the whole Product entry? I already have the ID so I hope that would be enough.
If you want to add or remove object without retrieving it, use stub entities: How to delete an object without retrieving it. Create stub, add to context, add to file.Products.
Why do you want to detach after loading?
Related
I'm a bit confused how to work properly with many-to-many relationships in locally created objects.
I've prepared a small example to demonstrate the issue.
There are two tables and one mapping table:
And data in tables:
Entity Framework has created two tables and many-to-many relation:
Now run the application and load single student (with ID=1 and his classrooms).
If student was loaded from the database then everything is fine and EF gets 2 classrooms:
But in case user was created locally (with the same Id but changed Name) and attached to the EF then classrooms are not loaded (studentLocal variable).
The same situation if I try to load student from EF - it gets the local user (student variable has Name="xx") and no classrooms:
On the view user can change classrooms for student as well as change student properties so I need to update Student table and merge StudentClassroom table.
What is the best way to deal in this case? I don't want to load each
postback student entity again and again.
Is there a way to load
Classrooms for locally created Student which exist in the database?
How to merge StudentClassroom records? I know only one - load
existed records and new one and merge then either deleting all of
them and recreating from the new list either manually determining
which records should be deleted/updated/created. Is there a better
approach?
Your problem is that EF is not creating the right tables for your model. It should be creating 3 classes not 2. Probably the reason it isn't is that you don't have the relations set up properly in the database. If you are using SQL Server try using the diagram feature to check your relationships and Primary Keys are correctly set up before you set up the model.
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'm building an iPad application where I need user to create entity dynamically. I'm already having 3 entities which program uses.
Could you help me with code how to do it?
I want to understand the whole structure according to my understanding I have to create new managedObjectModel, add new entities and than merge it with existing one, is it correct?
While it is possible to create a new entity and a new model on the fly in practice this is massively complex. If nothing else you would have to migrate any existing persisted data to the new model and a new persistent store file. I strongly recommend against attempting this especially if you are just starting out with Core Data.
You do have options:
Firstly, are you sure you actually need a new entity? People just starting out with Core Data often mistake entities for managed objects. Entities are to managed objects as classes are to instances. Entities are abstractions used to create the object graph. They don't actually contain data. The times when you need new entities are very,very rare.
Secondly, if you do need some kind of dynamic entity, it would usually be best to decompose the dynamic entity into numerous fixed subentities and then use relationships to create a virtual entity. E.g. you need a dynamic Person "entity" so you create several entities in the model each of which holds one attribute of the person. You could have a Field entity which would have a fieldName attribute and then a fieldValue attribute. Then have a an actual Person entity that has no attributes but just relationships to the necessary Field objects. You could add any fields needed to any person and then reconstitute an virtual person object by walking the relationships to its fields.
I rather doubt however that you need that kind of flexibility. Such a need is very rare. I would step back and see exactly what dynamic data you think the user might need to enter.
That's correct -- you'd create an array of NSEntityDescription objects, then call setEntities: on the new managed object model. Then, finally, you'd merge that model with your built-in model.
But note that you can't change a model once it has been used to create a managed object context (or used for storage). You'll need to create new storage and context after the model is changed.
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.
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.