使用GraphDiff更新多对多关联 [英] Update Many-to-Many Association with GraphDiff

查看:326
本文介绍了使用GraphDiff更新多对多关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下数据模型:

我的业务逻辑适用于分离的实体,所以我使用GraphDiff执行更新。我无法更新PerfModes / CalcPoints关联。在概念上,Block拥有CalcPoints和PerfModes,但CalcPoints可以与任意数量的PerfModes相关联。

My business logic works with detached entities so I'm using GraphDiff to perform updates. I'm having trouble updating the PerfModes/CalcPoints association. Conceptually, Block owns CalcPoints and PerfModes, but CalcPoints can be associated with any number of PerfModes.

我正在Block级别进行更新。我想出的代码不会抛出任何错误(而其他尝试),但也不更新PerfModes / CalcPoints关联。

I'm trying to do updates at the Block level. The code I came up with doesn't throw any errors (while other attempts did) but neither does it update the PerfModes/CalcPoints association.

container.UpdateGraph(block, map => map
    .OwnedCollection(b => b.HistPoints)
    .OwnedCollection(b => b.CalcPoints)
    .OwnedCollection(b => b.PerfModes, with => with
        .OwnedCollection(p => p.FilterCriterion, with2 => with2
            .OwnedCollection(fc => fc.Filters, with3 => with3
                .AssociatedEntity(f => f.OperatorType)
                .AssociatedEntity(f => f.CalcPoint))))
        .AssociatedCollection(p => p.CalcPoints)
);

我可能没有完全掌握EF图形和GraphDiff。如何确保多对多PerfModes / CalcPoints关联正确更新?

I probably don't have a full grasp of EF graphs and GraphDiff. How do I ensure that the many-to-many PerfModes/CalcPoints association gets updated correctly?

编辑

在查看了andyp的答案后,我从GitHub中下载了最新版本的GraphDiff,并尝试了以下映射:

After looking over andyp's answer, I pulled down the latest version of GraphDiff from GitHub and tried the following mappings:

container.UpdateGraph(block, map => map
    .OwnedCollection(b => b.CalcPoints)
    .OwnedCollection(b => b.PerfModes,
        with => with.AssociatedCollection(pm => pm.CalcPoints)));

这正确地更新了我的PerfModes / CalcPoints关联。我切换到我原来的映射,仍然看到协会没有更新的问题,所以试图一次更新整个模型似乎有问题。我可以做多个UpdateGraph电话,但是最好的方法是打破它们。

This correctly updates my PerfModes/CalcPoints association. I switched back to my original mappings and still saw the issue of the association not updating, so it seems there's a problem with trying to update the entire model at once. I'd be fine with making multiple UpdateGraph calls, but what would be the best way to break them out?

这是一个有相关代码和失败的单元测试的要点。

Here's a gist with relevant code and a failing unit test.

我继承了EF生成容器类以创建我自己的上下文,禁用代理创建。这是否导致GraphDiff的问题?

I'm inheriting the EF generated container class to create my own context with proxy creation disabled. Does that cause a problem with GraphDiff?

推荐答案

由于您的映射似乎是正确的,我试图重现您的问题,这个:

As your mappings seemed to be correct, I've tried to reproduce your issue like this:

var calcPoint = new CalcPoint();
var block = new Block
{
    CalcPoints = new List<CalcPoint> {calcPoint},
    PerfModes = new List<PerfMode> 
    {
        new PerfMode {CalcPoints = new List<CalcPoint> {calcPoint}}
    }
};

using (var context = new TestDbContext())
{
    context.UpdateGraph(block, map => map
        .OwnedCollection(b => b.CalcPoints)
        .OwnedCollection(b => b.PerfModes, 
            with => with.AssociatedCollection(pm => pm.CalcPoints)));

    context.SaveChanges();
}

using (var context = new TestDbContext())
{
    var reloaded = context.Blocks.Include("PerfModes.CalcPoints").Single();
    Assert.AreEqual(1, reloaded.CalcPoints.Count);
    Assert.AreEqual(1, reloaded.PerfModes.Count);
    Assert.AreEqual(1, reloaded.PerfModes[0].CalcPoints.Count);

    Assert.AreEqual(reloaded.CalcPoints[0], reloaded.PerfModes[0].CalcPoints[0]);
}

所有实体都是具有int键的简单POCO,只有我的 DbContext 中的IDbSet< T> s 。我没有通过流畅的API在 OnModelCreating(..)中添加任何内容,也不会在导航属性上使用任何属性。

All entities are simple POCOs with an int key and just IDbSet<T>s on my DbContext. I've neither added anything in OnModelCreating(..) via the fluent API nor used any attributes on the navigation properties.

我的代码正常工作,所以我有几个建议/问题:

My code above is working properly, so I've got a couple of suggestions / questions:

  • Is there anything (significant) you did differently then me above?
  • Do you call SaveChanges() after UpdateGraph()? It's not implied!
  • Do you have the latest version of GraphDiff? Please note, that the NuGet package is quite outdated, it's better to grab the current source from Github and build it yourself.
  • If your problem persists please update your question with the exact scenario that isn't working: please include the state of your DbContext before calling UpdateGraph(), the changes you expect GraphDiff to make and the ones it fails to make.

编辑
您的映射不正确, code> Block.CalcPoints 两次,一次作为拥有的集合(首先调用 OwnedCollection(..)),一次作为关联集合(最后只调用 AssociatedCollection(..))。所以你从来没有告诉GraphDiff来映射 PerfModes.CalcPoints ,反过来也不会更新该集合..; - )

EDIT: Your mapping wasn't correct after all, you're mapping Block.CalcPoints twice, once as an owned collection (first call to OwnedCollection(..)) and once as an associated collection (last and only call to AssociatedCollection(..)). So you never told GraphDiff to map PerfModes.CalcPoints and it, in turn, never updates that collection.. ;-)

要求GraphDiff这样做,请从最后一行之前的行尾移动到最后一行末尾的一个,你应该很好你的缩进与括号相匹配)。正确的映射看起来像这样(最后一行末尾有两个括号):

To ask GraphDiff to do that please move one ) from the end of the line before the last line to the end of the last line and you should be fine (after that your indentation matches the brackets). The correct mapping looks like this (two closing brackets at the end of the last line):

container.UpdateGraph(block, map => map
    .OwnedCollection(b => b.HistPoints)
    .OwnedCollection(b => b.CalcPoints)
    .OwnedCollection(b => b.PerfModes, with => with
        .OwnedCollection(p => p.FilterCriterion, with2 => with2
            .OwnedCollection(fc => fc.Filters, with3 => with3
                .AssociatedEntity(f => f.OperatorType)
                .AssociatedEntity(f => f.CalcPoint)))
        .AssociatedCollection(p => p.CalcPoints))
);

这篇关于使用GraphDiff更新多对多关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆