2010-12-30 36 views
8

Tôi đang đọc tệp bảng tính qua C# ... và bảng tính của tôi có hơn 1000 hàng. Tôi cần phải gửi mỗi hàng dữ liệu đến thủ tục lưu trữ để thực hiện một số logic cơ sở dữ liệu bên và cập nhật hồ sơ. Tôi cần một số trợ giúp để gửi tất cả 1000 hàng dữ liệu đó trong một chuyến đi khứ hồi duy nhất để tiết kiệm thời gian. Kỹ thuật cần phải nhóm tất cả 1000 hàng dữ liệu này là gì.Để chuyển hàng số lượng lớn dữ liệu vào các thủ tục được lưu trữ

+0

Bạn đang sử dụng SQL Server? Nếu bạn đang sử dụng phiên bản SQL Server nào? –

+1

1000 không phải là nhiều - bạn có chắc là bạn cần bận tâm không? Bạn có thể tìm thấy 1000 hàng tại một thời điểm không đưa ra bất kỳ vấn đề hiệu suất đáng chú ý nào. Nếu nó dễ dàng hơn để làm điều đó tại một thời điểm, tôi muốn cho rằng một thử đầu tiên và xem những gì sẽ xảy ra. –

Trả lời

20

Đoán rằng bạn đang sử dụng SQL Server 2008 hoặc tốt hơn, bạn có một vài tùy chọn. Tất cả các tùy chọn này được đề cập chi tiết tại Tech-Ed 2010 ở New Orleans và video of the session is available online. Dưới đây là tóm tắt các tùy chọn được trình bày.

Lựa chọn # 1 - Bulk Insert (không thực sự đề cập trong video)

Đây là một lựa chọn tuyệt vời nếu bạn chỉ cần phải "đổ" dữ liệu vào một bảng và bạn không cần phải làm nhiều với dữ liệu ngoại trừ đưa nó vào cơ sở dữ liệu. Điều này cũng được hỗ trợ trong ADO.NET bằng cách sử dụng đối tượng SqlBulkCopy. Tôi cũng đã viết một lightweight wrapper you can find on CodePlex để làm việc với SQL Server và ADO.NET dễ dàng hơn

Lựa chọn # 2 - Vượt qua một danh sách phân

Mang tất cả dữ liệu của bạn và xây dựng một chuỗi lớn và vượt qua toàn bộ chuỗi vào một thủ tục được lưu trữ. Điều này là đáng ngạc nhiên nhanh nhưng đi kèm với rất nhiều hành lý. Bạn phải có một hàm tách để lấy dữ liệu ra và để có được hiệu năng tốt nhất, bạn sẽ cần phải thực hiện việc chia tách với SQL-CLR và có thể là showstopper nếu bạn không sở hữu cơ sở dữ liệu.

Lựa chọn # 3 - Vượt qua như XML

này là gần như giống hệt nhau để Lựa chọn # 2 vì bạn đang đi qua một lần nữa trong một chuỗi khổng lồ vào một tham số. Điều này cũng có hiệu suất hợp lý nhưng cũng đi kèm với nhiều hành lý tương tự mà Option # 2 có nhưng không có chức năng tách vì Sql Server biết cách phân tích cú pháp XML.

Lựa chọn # 4 - Sử dụng một bảng Function Quý (SQL Server 2008)

Tùy chọn này rất mát mẻ và mang lại hiệu quả tốt nhất. Bạn bắt đầu bằng cách tạo một kiểu giá trị trong SQL Server thuộc kiểu "Bảng", sau đó bạn tạo một thủ tục lưu sẵn để lấy kiểu giá trị đó làm tham số. Trong C#, bạn có thể tạo một SqlCommand và thêm một tham số với một kiểu SqlDbType.Structured.

cmd.CommandType = CommandType.StoredProcedure; 
cmd.CommandText = "Test.spTVP"; 
var p = cmd.Parameters.Add("@Values", SqlDbType.Structured); 
p.TypeName = "Test.OrderTableType"; 
p.Value = dataTable; 
cmd.Execute…; 

Khi thủ tục lưu trữ được thực thi, tất cả dữ liệu có sẵn trong biến bảng của quy trình được lưu trữ. Nó có thể được sử dụng giống như bất kỳ biến bảng khác để di chuyển dữ liệu xung quanh rất đơn giản.

Lựa chọn # 5 - Sử dụng một streaming Bảng Quý Function (SQL Server 2008)

Một công việc ít hơn sau đó lựa chọn # 4 bởi vì bạn phải thiết lập một iterator nhưng bạn nhận được một số hiệu suất điên ra khỏi nó bởi vì bạn không phải tải tất cả dữ liệu trên máy khách trước khi chuyển nó vào thủ tục được lưu trữ. .NET Runtime sẽ thực sự truyền dữ liệu vào cơ sở dữ liệu và việc thực hiện thủ tục lưu sẵn là như nhau.

class MyStreamingTvp : IEnumerable<SqlDataRecord> { … 
} 
… 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.CommandText = "Test.spTVP"; 
var p = cmd.Parameters.Add("@Values", SqlDbType.Structured); 
p.TypeName = "Test.OrderTableType"; 
p.Value = new MyStreamingTvp(…); 
cmd.Execute…; 

Tất cả các tùy chọn này đều có chi tiết tuyệt vời và một chút hài hước trong số video Tôi đã đề cập ở đầu. Đó là một trong những phiên yêu thích của tôi tại Tech-Ed năm nay.

+0

+1: Tùy chọn rất tốt, tôi hy vọng tôi có thể bỏ phiếu nhiều hơn – TalentTuner

+0

@Saurabh Tôi đã làm điều đó cho bạn :-) –

+0

Hi Ryan, câu trả lời rất hay! Chỉ liên kết video không hoạt động nữa.Bạn có thể vui lòng đăng một liên kết mới hoặc bạn vẫn biết tiêu đề của phiên? Video phiên nên vẫn nằm trên cannel9 ... – Markus

3

Câu trả lời của Ryan rất kỹ lưỡng và bao gồm các tùy chọn khác nhau. Đối với một số lượng tương đối nhỏ của hàng (1000-5000 là khá nhỏ tất cả mọi thứ xem xét), tôi sẽ sử dụng những gì được vạch ra như là lựa chọn # 3, đi qua XML như là một tham số thủ tục lưu trữ. Chúng tôi thực hiện việc này thường xuyên trong cửa hàng của mình và sau đây là mã được liên kết với nó:

Tôi giả định rằng dữ liệu bảng tính của bạn đơn giản và bạn đã sẵn sàng trong mã của mình như một Danh sách bạn đã tạo hoặc một DataTable. Đối với ví dụ đơn giản này, tôi sẽ giả định rằng dữ liệu của bạn là một DataTable vì mục đích đơn giản.

tôi, giống như Ryan, cũng đang giả định SQL 2008.

1 - Chuẩn bị các dữ liệu trong C# bằng cách chuyển đổi các dữ liệu vào XML sẽ được chuyển đến các thủ tục lưu trữ. Đây chỉ là một chuỗi XML. Chúng tôi sử dụng một phương pháp trong lớp Cơ sở dữ liệu của chúng tôi. Bạn vượt qua trong DataTable của bạn và nó sẽ chuyển đổi nó thành một chuỗi XML đơn giản mà bạn có thể chuyển như một tham số cho thủ tục lưu sẵn của bạn.

public string ConvertToXMLDataString(DataTable table) { 
     StringBuilder XMLString = new StringBuilder(); 
     if (string.IsNullOrEmpty(table.TableName)) 
      table.TableName = "DataTable"; 
     XMLString.AppendFormat("<{0}>", table.TableName); 
     DataColumnCollection tableColumns = table.Columns; 
     foreach (DataRow row in table.Rows) { 
      XMLString.AppendFormat("<RowData>"); 
      foreach (DataColumn column in tableColumns) { 
       XMLString.AppendFormat("<{1}>{0}</{1}>", row[column].ToString(), column.ColumnName); 
      } 
      XMLString.AppendFormat("</RowData>"); 
     } 
     XMLString.AppendFormat("</{0}>", table.TableName); 
     return XMLString.ToString(); 
    } 

2 - Tôi đã tạo ra một ví dụ đơn giản DataTable sẽ chứa 1000 dòng dữ liệu, tất cả các số nguyên, 10 cột

DataTable table = new DataTable("DataTable"); 
      for(int i = 1; i < 11; i++){ 
       table.Columns.Add(new DataColumn("Column" + i.ToString())); 
      } 
      int j = 0; 
      for (int i = 0; i < 1000; i++) { 
       DataRow newRow = table.NewRow(); 
       for (int k = 0; k < table.Columns.Count; k++) { 
        newRow[k] = j++; 
       }    
       table.Rows.Add(newRow); 
      } 

Kết quả cuối cùng đi qua các DataTable để ConvertToXMLDataString là một độc đáo định dạng Biểu diễn XML của DataTable có thể được chuyển vào thủ tục được lưu trữ và dễ dàng được chọn từ:

<DataTable> 
    <RowData> 
     <Column1>0</Column1> 
     <Column2>1</Column2> 
     <Column3>2</Column3> 
     <Column4>3</Column4> 
     <Column5>4</Column5> 
     <Column6>5</Column6> 
     <Column7>6</Column7> 
     <Column8>7</Column8> 
     <Column9>8</Column9> 
     <Column10>9</Column10> 
    </RowData> 
    <RowData> 
     <Column1>10</Column1> 
     <Column2>11</Column2> 
     <Column3>12</Column3> 
     <Column4>13</Column4> 
     <Column5>14</Column5> 
     <Column6>15</Column6> 
     <Column7>16</Column7> 
     <Column8>17</Column8> 
     <Column9>18</Column9> 
     <Column10>19</Column10> 
    </RowData> 
</DataTable> 

3 - Bây giờ, tạo một thủ tục lưu sẵn để xử lý X Chuỗi dữ liệu ML đã được truyền vào nó.

CREATE PROCEDURE [dbo].[pr_Test_ConvertTable] 
@TableData XML 
AS 
BEGIN 
    SET NOCOUNT ON 
    SET ANSI_NULLS ON 
    SET ARITHABORT ON 

    DECLARE @TempTable TABLE (
     Column1 int, Column2 int, Column3 int, Column4 int, Column5 int, 
     Column6 int, Column7 int, Column8 int, Column9 int, Column10 int 
    ) 

    INSERT INTO @TempTable (Column1, Column2, Column3, Column4, Column5, Column6, Column7, Column8, Column9, Column10) 
    SELECT XmlTable.Data.value('(./Column1)[1]','int'), XmlTable.Data.value('(./Column2)[1]','int'), 
    XmlTable.Data.value('(./Column3)[1]','int'), XmlTable.Data.value('(./Column4)[1]','int'), 
    XmlTable.Data.value('(./Column5)[1]','int'), XmlTable.Data.value('(./Column6)[1]','int'), 
    XmlTable.Data.value('(./Column7)[1]','int'), XmlTable.Data.value('(./Column8)[1]','int'), 
    XmlTable.Data.value('(./Column9)[1]','int'), XmlTable.Data.value('(./Column10)[1]','int') 
    FROM @TableData.nodes('//DataTable/RowData') AS XmlTable(Data) 

    SELECT * FROM @TempTable 
END 
GO 

4 - Thủ tục chấp nhận biến XML của @TableData và chèn biến đó vào biến bảng mới được tạo tên @TempTable.

Bước cuối cùng là tạo cuộc gọi cơ sở dữ liệu của bạn với tham số XML thích hợp. Gọi SP như bình thường, chỉ cần sử dụng như là tham số.

cmd.Parameters.Add("@TableData", SqlDbType.Xml).Value = ConvertToXMLDataString(table); 

Bạn đã có. Bạn sẽ có thể điều chỉnh cho phù hợp để xử lý dữ liệu của mình. Tôi thường ghét truyền DataTables xung quanh, sẽ thay vì vượt qua một đối tượng, hoặc một danh sách xung quanh, nhưng trong tình huống này, bạn có thể có dữ liệu của bạn đã có trong DataTable.

Nếu điều này là một lần và được thực hiện, hoặc không phải là loại điều thường xuyên, hiệu suất nhấn bạn thực hiện để đổi lấy sự tiện lợi của việc sử dụng XML là tối thiểu. Nếu đây là điều xảy ra thường xuyên bởi nhiều người dùng, hãy sử dụng phương pháp tiếp cận hiệu quả hơn.

+0

Ồ, và tôi chưa bao giờ thực sự chọn SELECT *, điều đó thật đáng xấu hổ. Chỉ có cho ví dụ. Đừng làm vậy. –

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