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

すべてのエンティティは、 int キーとIDbSet<T>smyだけの単純な POCODbContextです。流暢な APIを介して何も追加OnModelCreating(..)したり、ナビゲーション プロパティの属性を使用したりしていません。

上記のコードは適切に機能しているため、いくつかの提案/質問があります。

  • あなたが上記のとは違うことをした(重要な)ことはありますか?
  • SaveChanges()の後に電話しUpdateGraph()ますか?暗示ではありません!
  • GraphDiff の最新バージョンを使用していますか? NuGet パッケージはかなり古くなっていることに注意してください。Githubから現在のソースを取得して自分でビルドすることをお勧めします。
  • 問題が解決しない場合は、動作していない正確なシナリオで質問を更新してください。DbContext呼び出す前の状態、 UpdateGraph()GraphDiff が行うと予想される変更、および失敗した変更を含めてください。

編集: 結局、マッピングは正しくありませんでした。所有コレクションとして 1 回 (への最初の呼び出しBlock.CalcPoints )OwnedCollection(..)と、関連付けられたコレクションとして 1 回 (最後の唯一の呼び出しAssociatedCollection(..)) を 2 回マッピングしています。したがって、GraphDiff にマップするように指示したことはPerfModes.CalcPointsなく、そのコレクションは決して更新されません.. ;-)

GraphDiff にそれを依頼する)には、最終行の前の行末から最終行の末尾に 1 つ移動してください。これで問題ありません (その後、インデントが括弧と一致します)。正しいマッピングは次のようになります (最後の行の終わりにある 2 つの閉じ括弧)。

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 に答える