说服实体上下文(EF1)填充实体引用

时间:2009-12-11 10:59:37

标签: entity-framework reference hierarchical-data

我有一个带自引用的实体(由实体设计师生成):

public MyEntity: EntityObject
{
    // only relevant stuff here
    public int Id { get...; set...; }
    public MyEntity Parent { get...; set...; }
    public EntityCollection<MyEntity> Children { get...; set...; }
    ...
}

我编写了一个存储过程,它从表中返回一个节点子树(只是直接子节点)并返回MyEntity个对象的列表。我正在使用存储过程来避免任意深树的延迟加载。这样,我就可以在一次调用中从DB中获取相关的子树节点。

List<MyEntity> nodes = context.GetSubtree(rootId).ToList();

一切都很好。但是当我检查nodes[0].Children时,它的Count等于0.但是如果我调试并检查context.MyEntities.Results view,则会填充子枚举。检查我的结果会显示我node[0]下的孩子。

我如何通过programaticaly强制我的实体上下文来做内存魔术并在ParentChildren属性上添加正确的引用?

更新1

我试过调用

context.Refresh(ClientWins, nodes);

GetSubtree()调用之后,它正确地设置了关系,但是再次从数据库中获取相同的节点。它仍然只是一种解决方法。但比使用context.MyEntities().ToList()得到整套更好。

更新2

我通过使用EF Extensions项目可靠地解决了这个问题。检查下面的答案。

2 个答案:

答案 0 :(得分:0)

您需要指定关系的一端。首先,划分集合:

var root = nodes.Where(n => n.Id == rootId).First();
var children = nodes.Where(n => n.Id != rootId);

现在,修复关系。

在您的情况下,您可以:

foreach (var c in children)
{
    c.Parent = root;
}

...或:

foreach (var c in children)
{
    root.Children.Add(c);
}

哪个没关系。

请注意,这会将实体标记为已修改。如果您打算在上下文中调用SaveChanges并且不想保存它,则需要更改它。

答案 1 :(得分:0)

REAL解决方案

基于this article(阅读问题下的文字),当使用存储过程返回数据时,导航属性显然不会被填充/更新。

但是有一个很好的手动解决方案。使用EF Extensions项目并编写您自己的实体Materilizer<EntityType>,您可以在其中正确设置导航属性,如下所示:

...
ParentReference = {
    EntityKey = new EntityKey(
        "EntityContextName.ParentEntitySetname",
        new[] {
            new EntityKeyMember(
                "ParentEntityIdPropertyName",
                reader.Field<int>("FKNameFromSP")
            )
        })
}
...

就是这样。调用存储过程将返回正确的数据,并且实体对象实例将彼此正确相关。我建议你查看EF Extensions的样本,在那里你会发现许多不错的东西。