3

我有以下数据模型:

数据模型

我的业务逻辑适用于分离的实体,因此我使用 GraphDiff 来执行更新。我在更新 PerfModes/CalcPoints 关联时遇到问题。从概念上讲,Block 拥有 CalcPoints 和 PerfModes,但 CalcPoints 可以与任意数量的 PerfModes 相关联。

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

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 关联?

编辑

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

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

这会正确更新我的 PerfModes/CalcPoints 关联。我切换回原来的映射,但仍然看到关联未更新的问题,因此尝试一次更新整个模型似乎存在问题。我可以进行多个 UpdateGraph 调用,但是将它们分解的最佳方法是什么?

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

我继承了 EF 生成的容器类来创建我自己的上下文,并禁用了代理创建。这会导致 GraphDiff 出现问题吗?

4

1 回答 1

2

由于您的映射似乎是正确的,我试图重现您的问题,如下所示:

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

所有实体都是简单的 POCO,带有一个 int 键,就IDbSet<T>s在我的DbContext. 我既没有OnModelCreating(..)通过 fluent API 添加任何东西,也没有在导航属性上使用任何属性。

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

  • 什么(重要的)你做的和我上面的不同吗?
  • 你打电话SaveChanges()UpdateGraph()吗?这不是暗示!
  • 你有最新版本的 GraphDiff 吗?请注意,NuGet 包已经过时了,最好从Github获取当前源并自己构建它。
  • 如果您的问题仍然存在,请使用不起作用的确切DbContext场景更新您的问题:请包括您调用之前的状态、UpdateGraph()您希望 GraphDiff 进行的更改以及它未能进行的更改。

编辑:您的映射毕竟不正确,您映射Block.CalcPoints 了两次,一次作为拥有的集合(第一次调用OwnedCollection(..)),一次作为关联的集合(最后一次也是唯一一次调用AssociatedCollection(..))。因此,您从未告诉 GraphDiff 进行映射PerfModes.CalcPoints,而反过来,它也永远不会更新该集合.. ;-)

要让 GraphDiff 这样做,请)从最后一行之前的行尾移动一个到最后一行的末尾,你应该没问题(之后你的缩进与括号匹配)。正确的映射如下所示(最后一行末尾的两个右括号):

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))
);
于 2014-05-24T10:33:20.027 回答