2012-04-13 37 views
9

Tôi đang cố gắng tìm sự khác biệt giữa việc sử dụng SqlBulkCopy với tùy chọn sao chép SqlBulkCopyOptions.UseInternalTransaction và không có nó, nhưng trong ứng dụng thử nghiệm của tôi, tôi không phát hiện bất kỳ sự khác biệt nào. Nếu BatchSize là ví dụ 0 và tôi thêm 100 bản ghi (trong một DataTable) trong đó bản ghi số 50 gây ra lỗi khi thêm nó vào bảng cơ sở dữ liệu, tôi nhận được 0 bản ghi trong bảng. Ví dụ: nếu BatchSize được đặt thành 10 ví dụ, tôi nhận được 40 bản ghi (4 đợt 10 bản ghi, đợt thứ năm bao gồm bản ghi bị lỗi và làm cho bản sao rời bỏ). Nó không quan trọng nếu S qlBulkCopyOptions.UseInternalTransaction được đặt hay không, tôi luôn nhận được kết quả tương tự. Dường như các lô luôn được sao chép trong giao dịch nội bộ.SqlBulkCopy: Sự khác nhau giữa việc truyền SqlBulkCopyOptions.UseInternalTransaction và không vượt qua nó là gì?

Nếu bạn quan tâm đến ứng dụng thử nghiệm của tôi, ở đây nó là: SqlBulkCopy-Error-and-Transaction-Test.zip

Câu hỏi của tôi là:

  1. SqlBulkCopyOptions.UseInternalTransaction lỗi thời vì SqlBulkCopy luôn luôn sử dụng các giao dịch nội bộ?
  2. Nếu không: Ý nghĩa thực sự của tùy chọn này là gì? Trong trường hợp nào nó sẽ tạo nên sự khác biệt?

Hope ai đó có thể làm rõ

Edit: Theo câu trả lời và những ý kiến ​​tôi cho rằng vấn đề của tôi ist không đủ rõ ràng. Tôi biết tài liệu. Nó nói rằng "Theo mặc định, một hoạt động sao chép số lượng lớn là giao dịch riêng của nó." và mỗi lô sử dụng giao dịch riêng của nó khi đi qua UseInternalTransaction. Nhưng nếu điều đó có nghĩa là theo mặc định, thao tác sao chép số lượng lớn chỉ sử dụng một giao dịch cho toàn bộ bản sao (và không phải một bản cho mỗi lô). Tôi sẽ không nhận được bản ghi trong cơ sở dữ liệu nếu tôi đặt BatchSize thành một kích thước nhất định và một lô nằm sau cái đầu tiên gây ra lỗi. Nếu chỉ có một giao dịch sẽ được sử dụng, tất cả các bản ghi được thêm vào nhật ký giao dịch sẽ được khôi phục. Nhưng tôi nhận được hồ sơ của các lô nằm trước lô có bản ghi bị lỗi. Theo điều này, có vẻ như là theo mặc định, mỗi lô được thực hiện trong giao dịch riêng của nó. Điều đó có nghĩa là nó không tạo sự khác biệt cho dù tôi có vượt qua UseInternalTransaction hay không. Nếu tôi trên con đường sai ở đây tôi sẽ thực sự đánh giá cao nếu ai đó có thể làm rõ.

Một thực tế có thể quan trọng: Tôi sử dụng SQL Server 2012. Có thể SQL Server 2008 hoạt động khác nhau. Tôi sẽ kiểm tra điều đó.

Chỉnh sửa: Nhờ câu trả lời từ usr Tôi nghĩ rằng tôi đã tìm thấy câu trả lời: Tôi đã sửa lỗi và lược tả một chút và phát hiện ra trường riêng _internalTransaction thực sự không được đặt nếu UseInternalTransaction không được xác định. SqlBulkCopy sau đó không sử dụng một giao dịch (nội bộ) riêng. Nhưng profiling chỉ ra rằng SqlBulkCopy sử dụng TDS (Tabular Data Stream) để sao chép dữ liệu (bất kể BatchSize là gì). Tôi không tìm thấy nhiều thông tin về TDS đặc biệt cho SQL Server nhưng tôi giả định rằng SQL Server thực hiện các hoạt động sao chép số lượng lớn TDS trong một giao dịch nội bộ. Do đó, UseInternalTransaction có vẻ là loại dự phòng cho SQL Server, nhưng ở bên an toàn, tôi sẽ thiết lập nó.

+0

http://msdn.microsoft.com/en-us/library/tchktcdk%28v=vs.80%29.aspx –

+0

Cảm ơn Tim. Có, tài liệu nói "Theo mặc định, hoạt động sao chép hàng loạt là giao dịch riêng của nó". Một chút sau nó nói "Bạn có thể chỉ rõ tùy chọn UseInternalTransaction trong constructor lớp SqlBulkCopy để gây ra một hoạt động sao chép lớn để thực thi trong giao dịch riêng của nó, khiến cho mỗi lô của hoạt động sao chép số lượng lớn thực thi trong một giao dịch riêng biệt". Điều này là khó hiểu. Và ứng dụng thử nghiệm của tôi không chỉ khác biệt! Xem bình luận của tôi cho câu trả lời từ Arion. Chỉ khi tôi vượt qua một giao dịch riêng, tôi nhận được 0 hồ sơ được thêm vào trong trường hợp có lỗi. Thử ứng dụng thử nghiệm của tôi ... –

+0

Tim Schmelter: Liên kết không liên quan. Nó không làm rõ vấn đề làm thế nào để viết ** một lô ** đến máy chủ mà không có một giao dịch. Nếu tôi hiểu câu hỏi của OP, đó không phải là cách làm cho toàn bộ hoạt động sao chép hàng loạt là một giao dịch. Tôi xác nhận tìm kiếm của Jurgen. UseInternalTransaction không hiệu quả trong trường hợp này. – JohnC

Trả lời

2

Nếu bạn đặt tùy chọn này thì lớp SqlBulkCopy sẽ thêm một

_internalTransaction = _connection.BeginTransaction(); 

xung quanh từng lô.

Nhưng tùy chọn này không tạo sự khác biệt thực tế với SQL Server dưới dạng giao dịch theo mặc định chạy ở chế độ tự động cam kết.

Sự khác biệt quan sát duy nhất là nó thực hiện xác thực mà bạn cũng không cố gắng chuyển vào giao dịch bên ngoài.

Sau đây sẽ thành công và rollback tất cả các lô

var transaction = sourceConnection.BeginTransaction();    
using (SqlBulkCopy bulkCopy = 
    new SqlBulkCopy(sourceConnection, SqlBulkCopyOptions.Default, transaction)) 

{ 
    bulkCopy.BatchSize = 50; 

    bulkCopy.DestinationTableName = "dbo.foobar"; 
     bulkCopy.WriteToServer(dt); 
} 

transaction.Rollback(); 

Đi qua SqlBulkCopyOptions.UseInternalTransaction thất bại với một lỗi

Không được chỉ định SqlBulkCopyOption.UseInternalTransaction và vượt qua một giao dịch bên ngoài cùng một lúc.

Tôi tự hỏi nếu nó có thể tạo sự khác biệt nếu một SET IMPLICIT_TRANSACTIONS ON; trước đây đã được chạy trên kết nối để tắt tự động chế độ nhưng sự quá tải của các nhà xây dựng SqlBulkCopy mà phải mất một đối tượng kết nối trả về một cam kết "giao dịch hiện bất ngờ." trong cả hai trường hợp xảy ra lỗi - và quá tải phải mất một chuỗi kết nối chỉ tạo ra một kết nối mới.

Các vấn đề liên quan