3

私は最近、あるデータベースから別のデータベースにデータをコピーするという私のニーズを Entity Framework が満たしていないところまで来ました (このままでは遅すぎるので、以前よりも多くのデータを取得したいと考えています)。そこで私は代替案を探し始め、そのSqlBulkCopy方法を見つけました。問題は、SqlBulkCopy「UPSERT」ができないことです。再び、解決策を探し始め、DataTable.Merge(table)関数に出会いました。

私の調査によると、「ベスト プラクティス」は、SqlBulkCopy を使用してデータを「ステージング テーブル」にインポートし、使用DataTable.Merge()して何らかの方法で変更を保存することです。変更を保存することは、私が問題に直面している部分です。次のコードがあります。

static void Main(string[] args)
    {
        using(var mdb = new meldbContext())
        using(var odb = new ocmgccazTestEnvDbContext())
        {
            /*Is there a better way to clear the staging table that
              doesn't require me to write actual SQL?*/
            odb.Database.ExecuteSqlCommand("DELETE FROM almCallDetail_staging");

            var lastUpdateTime = (from p in odb.almCallDetail
                                  select p.time_of_contact).Max();

            var query = from p in mdb.cl_contact_event
                        where p.time_of_contact >= lastUpdateTime
                        select new almCallDetail
                        {
                            id = p.id,
                            contact_list_name = p.contact_list_name,
                            account_number = p.account_number,
                            time_of_contact = p.time_of_contact
                        };

            var conn = new SqlConnection(odb.Database.Connection.ConnectionString);
            var bulkCopy = new SqlBulkCopy(conn)
            {
                BatchSize = 5000,
                DestinationTableName = "almCallDetail_staging"
            };

            conn.Open();
                bulkCopy.WriteToServer(query.ToDataTable());    

                var originalTable = (from p in odb.almCallDetail
                                     where p.time_of_contact >= lastUpdateTime
                                     select p).ToDataTable();

                var stagingTable = (from p in odb.almCallDetail_staging
                                    select p).ToDataTable();

                /*Merge happens but the data is not actually saved to the almCallDetail
                  Table (originalTable)...*/
                originalTable.Merge(stagingTable);
            conn.Close();
        }
    }

これを変更してマージ操作の結果を保存するにはどうすればよいですか?

かなり大量のデータをすばやくインポート/更新するという目標を達成するために、これをコーディングできるより良い方法はありますか?

詳細な説明:基本的には、(後で) グループのレポートに変換できるさまざまなデータセットを作成するために、運用サーバーのテーブルからデータを複製しているだけです。データを比較的最新の状態に保つために、このコードを 30 分ごとに実行するスケジュールされたタスクがあり、プロセス全体を可能な限り効率的にしたいと考えています。IE 運用サーバーから必要最小限のデータを取得し、それをローカル データベースにコピーします。

私の現在の実装は、完全に Entity Framework ベースです。これ:

  1. 本番サーバーから当日のデータ セットを取得します
  2. そのデータセットをループします
  3. それをローカルデータベースと比較します
  4. 必要に応じて更新/追加

それは私が必要とすることを正確に行いますが、非常に遅いです(いくつかの理由で、すべて理解しています)。したがって、それを更新したいという私の願望。

4

1 に答える 1

4

おそらくここで (SSIS を使用しない場合) 最も速い方法は、MERGEステートメントでストアド プロシージャを使用することです。
ストアド プロシージャにリンク サーバーを追加します。このようなものが動作するはずです:

exec sp_addlinkedserver @server = 'ProductionServer'

MERGE [LocalServer].dbName.dbo.TableName AS Target
USING (SELECT * FROM [ProductionServer].dbName.dbo.TableName) AS source
ON TARGET.Id = source.Id
WHEN MATCHED
THEN UPDATE 
SET Field1 = source.Field1, Field2 = source.Field2, ---etc....
WHEN NOT MATCHED BY TARGET THEN
INSERT (Field1, Field2, Field3) 
VALUES (Field1, Field2, Field3) ;

また、テーブルの 1 つからすべてを削除する必要がある場合は、TRUNCATE を使用してこれを行うことができます。これは よりもはるかに高速ですDelete from。このような:

TRUNCATE TABLE TableName;
于 2012-11-16T01:53:13.447 に答える