3

受け入れられた回答に基づく更新:

bool success = false;
using (var bulkCopy = new SqlBulkCopy(connection)) //using!
{
    connection.Open();

    //explicit isolation level is best-practice
    using (var tran = connection.BeginTransaction(IsolationLevel.ReadCommitted))
    {
        bulkCopy.DestinationTableName = "table";
        bulkCopy.ColumnMappings...

        using (var dataReader = new ObjectDataReader<SomeObject>(paths))
        {            
            bulkCopy.WriteToServer(dataReader);
            success = true;
        }

        tran.Commit(); //commit, will not be called if exception escapes
    }
}
return success;

BulkCopy大きなインサートにクラスを使用していますが、正常に動作します。
実行WriteToServerしてデータをデータベース
に保存した後、すべてのデータが正常に保存されていることを知りたくないのでtrue/false、すべてまたはまったく保存する必要があるため、戻ることができますか?

    var bulkCopy = new SqlBulkCopy(connection);

    bulkCopy.DestinationTableName = "table";

    bulkCopy.ColumnMappings...

    using (var dataReader = new ObjectDataReader<SomeObject>(paths))
    {
        try
        {
        bulkCopy.WriteToServer(dataReader);
        }
        catch(Exception ex){ ... }    
}
4

3 に答える 3

4

への呼び出しがWriteToServer例外なく完了した場合、すべての行が保存され、ディスク上にあります。これは、SQL Server DML の標準的なセマンティクスです。一括コピーに特別なことはありません。

他のすべての DML と同様に、SqlBulkCopyオール オア ナッシングです。設定しなかったバッチ サイズを設定した場合を除きます。

using (var bulkCopy = new SqlBulkCopy(connection)) //using!
{
    connection.Open();

    //explicit isolation level is best-practice
    using (var tran = connection.BeginTransaction(IsolationLevel.ReadCommitted))
    {
        bulkCopy.DestinationTableName = "table";
        bulkCopy.ColumnMappings...

        using (var dataReader = new ObjectDataReader<SomeObject>(paths))
        {
            //try
            //{
            bulkCopy.WriteToServer(dataReader, /*here you set some options*/);
            //}
            //catch(Exception ex){ ... } //you need no explicit try-catch here
        }

        tran.Commit(); //commit, will not be called if exception escapes
    }
}

ベスト プラクティスに沿ったサンプル コードを追加しました。

于 2013-10-01T11:37:49.123 に答える
1

メソッドによって発生した例外を検索/キャッチする以外に、プロセスが正常に完了したかどうかを識別する直接的な方法はありませんWriteToServer()

別の方法として、データベース内のレコード数を確認し、プロセスの完了後にレコード数を確認することもできます。違いは、挿入された数です。この値を挿入されるレコード数と比較すると、失敗か成功かがわかります。ただし、レコードを挿入/削除する他のプロセスがある場合は特に、これは絶対確実ではありません。

ただし、これらの手法をhttp://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspxTransactionScopeまたは同様のものと組み合わせることで、必要なものを実現できます。

編集

デフォルトでは、各挿入操作はバッチとして処理されます。特定のバッチで操作が失敗した場合、そのバッチはロールバックされ、その前に挿入されることはありません。

ただし、内部トランザクションが一括操作に適用される場合、いずれかの行でエラーが発生すると、結果セット全体がロールバックされる可能性があります。例えば;

using (SqlBulkCopy bulkCopy =
   new SqlBulkCopy(connectionString, SqlBulkCopyOptions.KeepIdentity
                   | SqlBulkCopyOptions.UseInternalTransaction))
{
   bulkCopy.BatchSize = 10;
   bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns";

   try
   {
      bulkCopy.WriteToServer(reader);
   }
   catch (Exception ex)
   {
      Console.WriteLine(ex.Message);
   }
   finally
   {
      bulkCopy.Close();
   }
}

上記の操作のいずれかでエラーが発生すると、操作全体がロールバックされます。詳細については、http://msdn.microsoft.com/en-us/library/tchktcdk.aspxを参照してください。

于 2013-10-01T11:21:16.503 に答える
0

この関数のドキュメントから、次のスニペットは、スローされた例外をキャッチする必要があることを示唆しています。そうしないと、操作が成功したと見なすことができます。

using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString))
{
     bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns";
     try
     {
         // Write from the source to the destination.
         bulkCopy.WriteToServer(reader);
     }
     catch (Exception ex)
     {
         Console.WriteLine(ex.Message);
     }
     finally
     {
         // Close the SqlDataReader. The SqlBulkCopy 
         // object is automatically closed at the end 
         // of the using block.
         reader.Close();
     }
}

確実に確認したい場合は、一括コピーが完了した後に、データベースに対してクエリを実行して行があることを確認します。

于 2013-10-01T11:15:56.720 に答える