Reputation: 10953
I am attempting to perform the LoadProperty operation from my context to load a navigation property of a navigation property.
My setup is that I have an EntityA, which contains a list of EntityB's, and each EntityB contains a list of EntityC's. I am doing the following programatically:
public virtual List<T> LoadProperty(List<T> entities, string property)
{
using (MyContext context = new MyContext())
foreach (T entity in entities)
{
context.AttachTo(typeof(T).Name, entity);
context.LoadProperty(entity, property);
}
return entities;
}
I call it as such:
LoadProperty(entityA, "EntityB.EntityC");
I know that the NavigationProperty path is correct, however, this is not working. Is there a way to get this to load?
Edit: Working example using Includes:
using (MyContext context = new MyContext())
{
var query = from entityA in context.EntityA.Include("EntityB").Include("EntityB.EntityC")
where entityA.Id == id
select entityA;
return query.ToList();
}
Upvotes: 3
Views: 3287
Reputation: 33216
First off, your method call context.AttachTo(typeof(T).Name, entity) is not correct and you'll get an InvalidOperationException. ObjectContext.AttachTo Method shows:
public void AttachTo(string entitySetName, Object entity)
So we need to pass the EntitySet name and not the Entity name itself. But the good news is we can get the EntitySet name from MetadataWorkspace by having the Entity name. The code below shows how.
Now if you have 3 levels of object composition and EntityB and EntityC are navigation properties of type EntityCollections, then I don’t think you could load them both with one call to LoadProperty, but you can do it by call LoadProperty twice, here is how it can be done:
using System.Data.Metadata.Edm;
public virtual List<T> LoadProperty(List<T> entities, string property) {
using (TrialsContext context = new TrialsContext()) {
EntityContainer container = context.MetadataWorkspace
.GetEntityContainer(context.DefaultContainerName,
DataSpace.CSpace);
EntitySetBase entitySet = container.BaseEntitySets
.Where(item =>
item.ElementType.Name.Equals(typeof(T).Name))
.FirstOrDefault();
foreach (T entity in entities) {
context.AttachTo(entitySet.Name, entity);
context.LoadProperty(entity, property);
}
return entities;
}
And you will call it:
// To load EntityA Nav property:
LoadProperty(entityB, "EntityA");
// To Load EntityC Nav property:
//Let's assume the nav property name for EntityC on EntityB is EntityCList
LoadProperty(entityB, "EntityCList");
This way you will have the full object graph constructed.
Upvotes: 1
Reputation: 126587
"I know that the NavigationProperty path is correct..." No it's not. Not with a list, it isn't. Try it with the regular Include
and you'll see the same result. You can't do this with 1:* properties.
I can't imagine this is the most efficient solution to your problem, but you haven't actually shown why you think you need this.
Upvotes: 1