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

发布于 2024-08-14 13:25:48 字数 1088 浏览 1 评论 0原文

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

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

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

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

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

如何以编程方式强制我的实体上下文执行内存中的魔法,并在 ParentChildren 属性上放置正确的引用?

UPDATE 1

我已经尝试

context.Refresh(ClientWins, nodes);

在我的 GetSubtree() 调用之后调用,该调用确实正确设置了关系,但再次从数据库中获取相同的节点。这仍然只是一个解决方法。但比使用 context.MyEntities().ToList() 获取整个集合要好。

更新 2

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

I have an entity with self reference (generated by Entity Designer):

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

I've written a stored procedure that returns a subtree of nodes (not just immediate children) from the table and returns a list of MyEntity objects. I'm using a stored proc to avoid lazy loading of an arbitrary deep tree. This way I get relevant subtree nodes back from the DB in a single call.

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

All fine. But when I check nodes[0].Children, its Count equals to 0. But if I debug and check context.MyEntities.Results view, Children enumerations get populated. Checking my result reveals children under my node[0].

How can I programaticaly force my entity context to do in-memory magic and put correct references on Parent and Children properties?

UPDATE 1

I've tried calling

context.Refresh(ClientWins, nodes);

after my GetSubtree() call which does set relations properly, but fetches same nodes again from the DB. It's still just a workaround. But better than getting the whole set with context.MyEntities().ToList().

UPDATE 2

I've reliably solved this by using EF Extensions project. Check my answer below.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傲影 2024-08-21 13:25:48

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

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 并且不希望保存它,则需要更改它。

You need to assign one end of the relationship. First, divide the collection:

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

Now, fix up the relationship.

In your case, you'd do either:

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

...or:

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

It doesn't matter which.

Note that this marks the entities as modfied. You'll need to change that if you intend to call SaveChanges on the context and don't want this saved.

梅倚清风 2024-08-21 13:25:48

真正的解决方案

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

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

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

就是这样。调用存储过程将返回正确的数据,并且实体对象实例将正确地相互关联。我建议您检查 EF Extensions 的示例,在那里您会发现很多好东西。

The REAL solution

Based on this article (read text under The problem), navigation properties are obviously not populated/updated when one uses stored procedures to return data.

But there's a nice manual solution to this. Use EF Extensions project and write your own entity Materilizer<EntityType> where you can correctly set navigation properties like this:

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

And that's it. Calling stored procedure will return correct data, and entity object instances will be correctly related to eachother. I advise you check EF Extensions' samples, where you will find lots of nice things.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文