EF 4.0 - 加载导航属性的导航属性

3

我正在尝试从我的上下文中执行LoadProperty操作,以加载导航属性的导航属性。

我的设置是我有一个EntityA,其中包含EntityB的列表,每个EntityB都包含EntityC的列表。我正在以编程方式执行以下操作:

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;
}

我称之为这样:

LoadProperty(entityA, "EntityB.EntityC");

我知道导航属性路径是正确的,但这并没有起作用。有没有办法让它加载?

编辑: 使用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();
}

你不需要同时调用Inclued("EntityB")和Include("EntityB.EntityC")。后者已经足够了。 - Ladislav Mrnka
EntityC是EntityB上的一个集合,因此在EntityB上没有EntityC。 - Morteza Manavi
2个回答

1
首先,你的方法调用 context.AttachTo(typeof(T).Name, entity) 是不正确的,你会得到一个 InvalidOperationException。ObjectContext.AttachTo 方法 表明:
public void AttachTo(string entitySetName, Object entity)

因此,我们需要传递EntitySet名称而不是实体名称本身。但好消息是,我们可以通过使用实体名称从MetadataWorkspace获取EntitySet名称。下面的代码显示了如何操作。

现在,如果您有3个级别的对象组合,并且EntityB和EntityC是类型为EntityCollections的导航属性,则我认为您无法通过一次调用LoadProperty来同时加载它们两个,但您可以通过两次调用LoadProperty来完成,以下是如何操作:

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;
}

你可以称之为:


// 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");

这样你就可以构建完整的对象图。


1
“我知道NavigationProperty路径是正确的…” 不,它不是。对于列表来说,它不是正确的。尝试使用常规的Include,你会看到相同的结果。你不能在1:*属性中这样做。
我无法想象这是解决你问题最有效的方法,但你实际上没有展示出为什么你认为你需要这个方法。

我已经使用Include进行了测试,它可以正常工作。请查看编辑后的工单。当传递我的EntityA实例时,有这样的需求。初始屏幕可能不需要某个导航属性,但是后续屏幕可能需要。我希望能够仅调用LoadProperty来加载所需的属性,而不是重新使用Includes加载实体。LoadProperty方法可用于加载属性“EntityB”,但无法加载“EntityB.EntityC”。 - Brandon
如果 Include() 能够正常工作,那么它比显式加载更有效率。但是投射到视图模型会比两者都更有效率。 - Craig Stuntz
在审查LoadProperty文档时,我没有看到任何迹象表明它旨在支持点路径。 - Craig Stuntz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接