Supose I have following entities created from database tables:
Person
Student
Student include Person as navigation property.
Person has navigation property Country to connect lookup table Country.
In Student metadata, I do put [Include] for navigation property Person.
In Person metadata, I do put [Include] for navigation property Country.
When loading student data, I want to eager loading like to include Person and Country data:
this.ObjectContext.Students.Include("Person").Include("Country");
This was working fine when I use previous version of ASP.NET Data Ria Service. Now when it is changed to WCF Ria Service, above way not working any more.
System give me the error said Country is not a navigation property of Student.
How to resolve this problem?
The error is correct.
Include is on the ObjectQuery<T> you are querying, in this case "Students".
Country is a navigational property of Person, not Student.
Change your code to this:
this.ObjectContext.Students.Include("Person").Include("Person.Country");
Or simply:
this.ObjectContext.Students.Include("Person.Country");
As EF will automatically include "Person" based on the nested include.
You need to remember that Include returns an ObjectQuery<T> based on the ObjectQuery<T> it was invoked upon.
So just because your doing Students.Include("Person"), that doesn't mean at that point, the variable is ObjectQuery<Person> - the variable is still ObjectQuery<Student>.
Related
in code first, When I want to save 2 related entities (for example Country entity and City entity), first, I create an instance of Country and second create an instance of City and put object of Country to navigation of City, at last SaveChanges.in this process Database, first, create the Country and then put its Id to CountryId field of City entity and save city to database. so now, I want to do the same but with non-related entities. this means I want to send 2 entity (without relationship) to DB, that fist, first one saved and second one get its Id, and use it, at last Save...
In my app, Im using CoreData and I have two entities. VenueInfo and ContactInfo.
In the app, you can add venues, and each venue has ContactInfo. So I've setup a one to one relationship in my model.
So I would imagine, I could simply do the following:
[venue.contact setValue:textField.text forKey:email];
So like so you'd set the email attribute of the contact object which belongs to the venue. However this doesn't work.
Is it possible because the contact object doesn't exist yet?
The line you wrote won't work that way. I assume contact is the relationship name you have in your Venue entity in xCodeModel.
[venue.contact setValue:textField.text forKey:email]; // can't write this way..
Suppose your ContactInfo entity has two fields : phone, email so this way you can go.
and VenueInfo entity has two fields : name.
VenueInfo *venueInfo=[NSEntityDescription insertNewObjectForEntityForName:#"VenueInfo" inManagedObjectContext:self.managedObjectContext];
vanueInfo.name=txtVenueName.text; // venue name entry
ContactInfo *contactInfo=[NSEntityDescription insertNewObjectForEntityForName:#"ContactInfo" inManagedObjectContext:self.managedObjectContext];
contactInfo.phone=txtPhone.text;
contactInfo.email=txtEmail.text;
contactInfo.venue=venueInfo; // I assume venue is the relationship name you give in ContactInfo entity towards Venue entity.
What we did here is we saved phone and email details to ContactInfo entity only and then we just related it with currently selected VenueInfo accessing the relationship we declared in ContactInfo Entity for VenueInfo.
This maybe quite confusing so I'll recommend you to follow a few tutorials which will give you an idea to grasp some basics about core data relationships.
I'm fairly new to EF and STE's, but I've stumbled on a painful point recently, and I'm wondering how others are dealing with it...
For example, suppose I have two STE's: Employee and Project. It's a many-to-many relationship. Each entity has a navigation property to the other (i.e. Employee.Projects and Project.Employees).
In my UI, a user can create/edit an Employee and associate it with multiple Projects. When the user is ready to commit, a list of Employees is passed to the server to save. However, if an Employee is not added to the "save list" (i.e. it was discarded), but an association was made to one or more Projects, the ApplyChanges extension method is able to "resurrect" the Employee object because it was "connected" to the object graph via the association to a Project.
My "save" code looks something like this:
public void UpdateEmployees(IEnumerable<Entities.Employee> employees)
{
using (var context = new EmployeeModelContainer(_connectionString))
{
foreach (var employee in employees)
{
context.Employees.ApplyChanges(employee);
}
context.SaveChanges();
}
}
I've been able to avoid this issue to now on other object graphs by using FKs to manipulate associations as described here: http://blogs.msdn.com/b/diego/archive/2010/10/06/self-tracking-entities-applychanges-and-duplicate-entities.aspx
How does one handle this when a many-to-many association and navigation properties are involved?
Thanks.
While this answer's a year late, perhaps it will be of some help to you (or at least someone else)
The simple answer is this: do not allow Entity Framework to infer m:m relationships. Unfortunately, I'm not aware of a way of preventing this, only how to deal with it after the fact.
By default, if I have a schema like this:
Employee EmployeeProject Project
----------- --------------- ----------
EmployeeId ---> EmployeeId |--> ProjectId
Name ProjectId ----- Name
... ...
Entity Framework will see that my EmployeeProject table is a simple association table with no additional information (for example, I might add a Date field to indicate when they joined a project). In such cases, it maps the relationship over an association rather than an entity. This makes for pretty code, as it helps to mitigate the oft-referenced impedence mismatch between a RDBMS and object-oriented development. After all, if I were just modeling these as objects, I'd code it the same way, right?
As you've seen, however, this can cause problems (even without using STE's, which cause even MORE problems with m:m relationships). So, what's a dev to do?
(The following assumes a DATABASE FIRST approach. Anything else and you're on your own)
You have two choices:
Add another column to your association table so that EF thinks it has more meaning and can't map it to an association. This is, of course, bad design, as you presumably don't need that column (otherwise you'd already have it) and you're only adding it because of the particular peculiarities of the ORM you've chosen. So don't.
After your context has been generated, map the association table yourself to an entity that you create by hand. To do that, follow the following steps:
Select the association in the designer and delete it. The designer will inform you that the table in question is no longer mapped and will ask you if you want to remove it from the model. Answer NO
Create a new entity (don't have it create a key property) and map it to your association table in the Mapping Details window
Right-click on your new entity and add an association
Correct the entity and multiplicity values (left side should have your association entity with a multiplicity of *, right should have the other entity with a multiplicity of 1)
Check the option that says "Add foreign key properties to the Entity"
Repeat for the other entity in the association
Fix the property names on the association entity (if desired...not strictly necessary but they're almost certainly wrong) and map them to the appropriate columns in the Mapping Details window
Select all of the scalar properties on your association entity and set them as EntityKey=True in the Properties window
Done!
I'm looking for advice on a decent pattern for dropdown list selection and persistence of the selection with POCO EF please.
I have a list of IEnumerable<Country> in my view model where Country is a POCO loaded via EF. There is an Address property on the view model that takes the current or user selected value on it's Country property. Within the view I display these via a Html.DropdownListFor() thus:
Html.DropDownListFor(model => model.Address.Country.Id, new SelectList(Model.Countries,"Id","Name",model.Address.Country.Id)
So far so good and it all works on postback with the default ModelBinder providing me with a view model with the Address.Country populated. However Address.Country is of course only populated with the Id field with default model binding.
Trying to send the Address update back to the DB through EF blows up as this is seen as a new object which doesn't have it's full object graph loaded, only the Id set.
Now I can fix this by loading the full Country object from the db into the Address.Country property on postback before saving based on the selected Id. But this seems like a lot of hard work for anything beyond a simple object graph.
The most "elegant" solution I could think of would be a custom model binder for Country but then that would require the Model Binder to know about the repository for retrieving the full EF object which doesn't seem right to me. I'd also have to repeat this for all other Entities used in Dropdown lists.
Hope this makes sense and any feedback on how others are doing this would be appreciated.
If you set Address.Country to an object, EF expects it to be a full object that's part of the current context, but EF does recognize foreign keys: If your Address object has both a CountryID property and a Country property, it should accept Address.CountryID being set as long as Address.Country itself is null.
In your Address class declare country as virtual
public class Address
{
public virtual Country Country;
}
try this and let me know if it works, Virtual supports lazyloading and you don't have to query explicitly
I am using the Entity Framework with SQL Server. I have a many to many relationship between 2 tables. I have created a join table with just the primary key fields of the 2 tables. In the designer, the 2 tables now have a navigation property to the other with return types of Collection of X where X is the other entity. So far, everything just as it should be. The setup looks correct.
Task TaskProducts Product
========== ============ =======
TaskID TaskID ProductID
Description ProductID Name
Not every task will have a product or products associated with it. What do I assign to the Products navigation property of the Task table when there is no associated Product for that Task?
Do I build up a EntityCollection collection with the Product entities and assign that to the Products navigation property on the Task entity when I do have Product entities?
When doing updates(adding, removing and changing) to the Products navigation property on the Task entity, do I work with it like any other collection? Are there any special things to look out for?
I would be interested in any help working with many to many relationships in the Entity Framework.
Edit(11/17/2009)
One thing I learned is that to a many to many relationship work with a join table, BOTH fields in the join table need to be marked as primary keys;
MSDN has good documentation on managing many-to-many relationships in the Entity Framework:
http://msdn.microsoft.com/en-us/library/bb738695.aspx
The prescriptive guidance for inserts is to call the "Add" method on the entity collection and specify the related object (versus setting the Value property on the entity reference for a one-to-many relationship.)
Updates are handled just like any other EF update... load the desired object, set the changed properties and call SaveChanges on the context.
Deletes are handled the same as well, call DeleteObject on the context and then SaveChanges.