2010-05-21 46 views
6

Tôi tự hỏi có cách nào để cập nhật hàng loạt không? Tôi đang sử dụng máy chủ sql ms 2005.Làm thế nào để thực hiện cập nhật hàng loạt?

Tôi đã thấy bằng cách sử dụng sqlDataAdaptor nhưng có vẻ như trước tiên bạn phải chọn câu lệnh với nó, sau đó điền một số tập dữ liệu và thực hiện thay đổi cho tập dữ liệu.

Bây giờ tôi đang sử dụng LINQ to sql để thực hiện lựa chọn vì vậy tôi muốn cố gắng giữ nó theo cách đó. Tuy nhiên nó là quá chậm để làm cập nhật lớn. Vì vậy, có đi mà tôi có thể giữ linq của tôi để sql (cho phần chọn) nhưng bằng cách sử dụng một cái gì đó khác nhau để làm cập nhật hàng loạt?

Cảm ơn

Sửa

Tôi quan tâm đến cách dàn dựng bảng này, nhưng tôi không chắc chắn làm thế nào để làm điều đó và vẫn chưa rõ làm thế nào nó sẽ nhanh hơn kể từ khi tôi không hiểu như thế nào phần cập nhật hoạt động.

Vì vậy, bất kỳ ai cũng có thể cho tôi biết cách thức này sẽ hoạt động và cách xử lý các kết nối đồng thời?

Edit2

Đây là nỗ lực mới nhất của tôi lúc cố gắng để làm một cập nhật hàng loạt sử dụng xml tuy nhiên nó sử dụng các nguồn lực nhiều và lưu trữ chia sẻ của tôi không cho phép nó đi qua. Vì vậy, tôi cần một cách khác nhau để thats lý do tại sao tôi không nhìn vào một bảng dàn dựng.

using (TestDataContext db = new TestDataContext()) 
      { 
       UserTable[] testRecords = new UserTable[2]; 
       for (int count = 0; count < 2; count++) 
       { 
        UserTable testRecord = new UserTable(); 

        if (count == 1) 
        { 
         testRecord.CreateDate = new DateTime(2050, 5, 10); 
         testRecord.AnotherField = true; 
        } 
        else 
        { 
         testRecord.CreateDate = new DateTime(2015, 5, 10); 
         testRecord.AnotherField = false; 
        } 


        testRecords[count] = testRecord; 
       } 

       StringBuilder sBuilder = new StringBuilder(); 
       System.IO.StringWriter sWriter = new System.IO.StringWriter(sBuilder); 
       XmlSerializer serializer = new XmlSerializer(typeof(UserTable[])); 
       serializer.Serialize(sWriter, testRecords);    

       using (SqlConnection con = new SqlConnection(connectionString)) 
       { 
        string sprocName = "spTEST_UpdateTEST_TEST"; 

        using (SqlCommand cmd = new SqlCommand(sprocName, con)) 
        { 
         cmd.CommandType = CommandType.StoredProcedure; 

         cmd.CommandType = System.Data.CommandType.StoredProcedure; 

         SqlParameter param1 = new SqlParameter("@UpdatedProdData", SqlDbType.VarChar, int.MaxValue); 
         param1.Value = sBuilder.Remove(0, 41).ToString(); 
         cmd.Parameters.Add(param1); 
         con.Open(); 
         int result = cmd.ExecuteNonQuery(); 
         con.Close(); 
        } 
       } 
      } 

@ Fredrik Johansson Tôi không chắc chắn câu nói của bạn sẽ hoạt động. Có vẻ như với tôi, bạn muốn tôi đưa ra tuyên bố cập nhật cho mỗi bản ghi. Tôi không thể làm điều đó vì tôi sẽ cần cập nhật 1 đến 50.000 bản ghi và tôi sẽ không biết cho đến thời điểm đó.

Sửa 3

Vì vậy, đây là SP của tôi bây giờ. Tôi nghĩ rằng nó sẽ có thể làm kết nối đồng thời nhưng tôi muốn chắc chắn.

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE PROCEDURE [dbo].[sp_MassUpdate] 
@BatchNumber uniqueidentifier 
AS 
BEGIN 
    update Product 
    set ProductQty = 50 
    from Product prod 
    join StagingTbl stage on prod.ProductId = stage.ProductId 
    where stage.BatchNumber = @BatchNumber 

    DELETE FROM StagingTbl 
    WHERE BatchNumber = @BatchNumber 

END 
+0

Bạn có thể giải thích/biện minh cho bình luận của mình lại không. Các vấn đề hiệu suất cập nhật LINQ to SQL? –

+0

Về cơ bản nó đi xuống này. Tôi muốn chèn 500 bản ghi và cập nhật 500 bản ghi. Xác nhận mất 1 phút và 58 giây, chèn với bản sao số lượng lớn mất 2seconds và sử dụng LINQ to sql để cập nhật tất cả 500 hàng và chèn chúng mất 4 phút. Tôi muốn nhận được rằng kể từ khi tôi có thể sẽ cần phải cập nhật lên tới 30.000 đến 50.000 hàng. Tuy nhiên tôi không muốn linq để sql để làm việc lựa chọn và thao tác như tôi thấy nó dễ dàng hơn để làm việc với một đối tượng. Tôi không quan tâm khi nói đến bản cập nhật những gì nó trông giống như nó sẽ được dễ dàng nếu tôi có tất cả các hồ sơ thao tác và tôi chỉ có thể trích xuất các giá trị – chobo2

+0

của mỗi đối tượng LINQ với một vòng lặp for và ném nó vào những gì bao giờ là bắt buộc. – chobo2

Trả lời

1

Như tên gọi đã nói, Sử dụng SqlBulkCopy, rất nhanh (tôi đã tìm thấy các cải tiến tốc độ trên 200x - từ 1500 giây đến 6 giây). Tuy nhiên, bạn có thể sử dụng các lớp DataTable và DataRows để cung cấp dữ liệu cho SQlBulkCopy (có vẻ dễ dàng hơn). Sử dụng SqlBulkCopy theo cách này có thêm lợi thế của bein .NET 3.0 tuân thủ (Linq đã được bổ sung chỉ trong 3.5).
Thanh toán http://msdn.microsoft.com/en-us/library/ex21zs8x%28v=VS.100%29.aspx đối với một số mã mẫu.

0

Bạn phải làm việc trực tiếp với cây biểu thức, nhưng có thể thực hiện được. Trong thực tế, nó đã được thực hiện cho bạn, bạn chỉ cần tải về nguồn:

Batch Updates and Deletes with LINQ to SQL

Cách khác là chỉ cần sử dụng thủ tục lưu trữ hoặc đột xuất quảng cáo truy vấn SQL bằng cách sử dụng ExecuteMethodCallExecuteCommand phương pháp của DataContext .

+0

Bạn có thể giải thích phương án này? Tôi không quan tâm nếu một phần cập nhật là trong một SP hoặc ado.net tất cả tôi quan tâm là đến thời điểm đó tôi thay vì có lựa chọn và thao tác trong LINQ để sql vì vậy tôi có thể đối phó với các đối tượng. Sau khi tôi thực hiện thao tác chúng sau đó tôi không quan tâm làm thế nào họ nhận được cập nhật cơ sở dữ liệu. – chobo2

+0

@ chobo2: Tôi không chắc phải giải thích gì - nếu bạn có thể viết logic cập nhật hoàn toàn trên máy chủ, làm thủ tục lưu trữ, sau đó chỉ cần kéo SP đó vào bề mặt thiết kế LINQ to SQL và chạy nó. Mặc dù vậy, sẽ không giúp bạn ghi lại bằng bản ghi, nếu bạn đang cố gắng thực hiện các bản cập nhật khác nhau cho một nghìn bản ghi; cách duy nhất để tăng tốc quá trình đó là sử dụng Tham số Bảng-Giá trị hoặc chèn hàng loạt vào một bảng dàn, không hỗ trợ LINQ to SQL nào. – Aaronaught

+0

bảng dàn xếp này hoạt động như thế nào? – chobo2

1

Sử dụng SqlBulkCopy cực nhanh. Bạn sẽ cần một triển khai IDataReader tùy chỉnh liệt kê các kết quả truy vấn LINQ của bạn. Hãy xem http://code.msdn.microsoft.com/LinqEntityDataReader để biết thêm thông tin và một số mã IDataReader thích hợp.

1

Bạn có thể sử dụng sqlDataAdapter để thực hiện cập nhật hàng loạt. Việc bạn điền dữ liệu của mình là không quan trọng. L2SQL hoặc bất cứ điều gì, bạn có thể sử dụng các phương pháp khác nhau để thực hiện cập nhật. Chỉ cần xác định truy vấn để chạy bằng cách sử dụng dữ liệu trong datatable của bạn.

Chìa khóa ở đây là UpdateBatchSize. Dataadapter sẽ gửi các bản cập nhật theo lô bất kỳ kích thước nào bạn xác định. Bạn cần hết hạn với giá trị này để xem số nào hoạt động tốt nhất, nhưng con số điển hình của 500-1000 là tốt nhất.SQL sau đó có thể tối ưu hóa việc cập nhật và thực thi nhanh hơn một chút. Lưu ý rằng khi thực hiện batchupdates, bạn không thể cập nhật nguồn hàng của datatable.

Tôi sử dụng phương pháp này để cập nhật 10-100K và thường chạy trong chưa đến 2 phút. Nó sẽ phụ thuộc vào những gì bạn đang cập nhật mặc dù.

Xin lỗi, đây là trong VB….

Using da As New SqlDataAdapter 
     da.UpdateCommand = conn.CreateCommand 
     da.UpdateCommand.CommandTimeout = 300 

     da.AcceptChangesDuringUpdate = False 
     da.ContinueUpdateOnError = False 
     da.UpdateBatchSize = 1000 ‘Expirement for best preformance 
     da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 'Needed if UpdateBatchSize > 1 
     sql = "UPDATE YourTable" 
     sql += " SET YourField = @YourField" 
     sql += " WHERE ID = @ID" 
     da.UpdateCommand.CommandText = sql 
     da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 
     da.UpdateCommand.Parameters.Clear() 
     da.UpdateCommand.Parameters.Add("@YourField", SqlDbType.SmallDateTime).SourceColumn = "YourField" 
     da.UpdateCommand.Parameters.Add("@ID", SqlDbType.SmallDateTime).SourceColumn = "ID" 

     da.Update(ds.Tables("YourTable”) 
End Using 

Một tùy chọn khác là ghép hàng loạt vào bảng tạm thời, sau đó chạy truy vấn để cập nhật bảng chính từ bảng đó. Điều này có thể nhanh hơn.

0

Bạn có thể sử dụng SqlDataAdapter để thực hiện cập nhật hàng loạt ngay cả khi dữ liệu có thể được điền thủ công/lập trình (từ linq của bất kỳ nguồn nào khác).

Chỉ cần nhớ đặt thủ công RowState cho các hàng trong cột dữ liệu. Sử dụng dataRow.SetModified() cho việc này.

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