0

先週、再現しようとしたバグがありました。既存のコードの一部がデータベースに一括挿入を行いました。ただし、データベース内で値を複製することはできませんでした。古いコードでは、SaveChanges を使用して AddObject を実行するたびに変更がデータベースに保存されていました。これはあまりうまく機能していませんでした。そのため、1000 レコードごとに毎回保存するのではなく (トランザクションでこれを行いましたが、このサンプルには関係ありません)。

以下のこのコードは、私が行ったことの概要を示しています。

        TestEntities test = new TestEntities();

        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                string q = j.ToString();
                if (!test.warehouses.Any(x => x.combi == q))
                {
                    warehouse wh = new warehouse();
                    wh.combi = j.ToString();
                    wh.ean = j.ToString();
                    test.warehouses.AddObject(wh);
                }
            }

        }
        test.SaveChanges();

私が知らなかったのは、エンティティ フレームワークは保留中のデータではなくデータベース内のデータのみをクエリするため、任意のクエリはデータベースで結果を返さないことでした (結果があると想定していました)。したがって、これは望ましくない結果になります。上記のコードで重複しています。

今のところ、すぐに追加されるすべてのオブジェクトをメモリに保存してからデータベースに保存するように解決しました。これは機能しますが、コードに多くのオーバーヘッドが生じます。この問題を回避する方法はありますか? データベースと保留中の変更を処理するように EF に指示できますか? すべての ORM はこのように機能していますか?

ありがとう、パトリック

4

1 に答える 1

1

同様の問題に直面して、私はあなたと同じようにデータベースをチェックし、ローカルデータをチェックすることにしました:

    if( !test.warehouses.Local.Any(x => x.combi == q ) 
        && !test.warehouses.Any(x => x.combi == q ) )

これはうまくいくはずです。

編集: しかし、そうではありません。ただし、これは次のことを行います。

var isLocal = ( test as System.Data.Objects.ObjectContext ).ObjectStateManager
    .GetObjectStateEntries( System.Data.EntityState.Added )
    .Any( x => (x.Entity as warehouse).combi == q );
if( !isLocal && !test.warehouses.Any( x => x.combi == q ) ) {
    // ...
}

(モデル デザイナーによって作成されるIDbSet<>のではなく、最初にコードによって使用される) にはプロパティがあるため、 ObjectStateManagerをクエリする必要はありません。Code Firstは完全に異なるものであることは知っていますが、非常に効率的です。Microsoft SQL Server Management Studio を使用してデータベースを設計し、 Entity Framework Power Toolsからデフォルトまたはカスタマイズされた (必要に応じて) T4 テンプレートを使用して優れたリバース エンジニア Code Firstを実行します。ほとんど何でも手に入れる。http://en.wiktionary.org/wiki/your_mileage_may_varyObjectSet<>.Local

于 2012-09-15T14:21:28.510 に答える