Helpex - Trao đổi & giúp đỡ Đăng nhập
2

Tôi có một bảng SQL Server với khoảng 8 triệu bản ghi cho một dự án nghiên cứu và tôi cần tính toán một vài giá trị cho mỗi bản ghi và lưu chúng vào bản ghi. Việc tính toán khá phức tạp, vì vậy việc tôi thiếu kiến ​​thức về T-SQL có nghĩa là tôi muốn thực hiện xử lý bằng cách sử dụng .net mặc dù kịch bản T-SQL chắc chắn là lựa chọn tốt nhất.

Cách tiếp cận của tôi rất đơn giản, nhưng nó vẫn không thành công. Tôi đang sử dụng trình đọc dữ liệu (có kết nối riêng) để lặp lại tất cả các bản ghi. Tôi đang sử dụng một kết nối khác để tạo lệnh thực thi các bản cập nhật bằng thủ tục được lưu trữ. Sau khoảng một triệu, nó không thành công với lỗi hết thời gian chờ.

Lúc đầu, tôi đã thử với EF, nhưng điều đó rất chậm và tôi gặp khó khăn trong việc ngăn các ngoại lệ về bộ nhớ mặc dù tôi đã thử nhiều cách tiếp cận khác nhau.

Cách tốt nhất để thực hiện việc này bằng cách sử dụng .net là gì? Tôi đang sử dụng các kết nối sai? Tôi đã đọc rằng việc sử dụng sai nhiều kết nối có thể dẫn đến ngoại lệ thời gian chờ.

Đây là một ví dụ về mã (VB.NET):

Public Sub UpdateRecords()

    Dim ReadConnection As New SqlConnection("ConnectionString")
    Dim WriteConnection As New SqlConnection("ConnectionString")
    Dim Reader As SqlDataReader
    Dim ReadCommand As SqlCommand
    Dim WriteCommand As SqlCommand
    Dim Transaction As SqlTransaction

    ReadConnection.Open()
    ReadCommand = New SqlCommand("select * from records", ReadConnection)
    Reader = ReadCommand.ExecuteReader
    If Reader.HasRows Then
        WriteConnection.Open()
        Transaction = WriteConnection.BeginTransaction
        Do While Reader.Read
            WriteCommand = New SqlCommand("StoredProcedure", WriteConnection, Transaction)
            'calculate
            'set parameters
            WriteCommand.ExecuteNonQuery()
        Loop
        Transaction.Commit()
        WriteConnection.Close()
    End If
    Reader.Close()
    ReadConnection.Close()

End Sub
2 hữu ích 5 bình luận 1.5k xem chia sẻ
0

Bởi vì có rất nhiều bản ghi, không khả thi để tải tất cả chúng và sau đó cập nhật từng cái một. Đặc biệt nếu bạn phải thực hiện các phép tính trong VB.NET.

Tôi khuyên bạn nên tải chúng theo lô, tính toán từng lô và cuối cùng cập nhật lại theo lô (kích thước lô nên được đặt thành giá trị không làm cho các phép tính kéo dài mãi mãi trên mỗi lô).

Về cách bạn có thể cập nhật hàng loạt, tôi sẽ để điều này ở đây . Nó nói về cách bạn có thể sử dụng các tham số có cấu trúc để cập nhật / chèn.

Các lựa chọn thay thế khác bao gồm:

  1. Thực hiện các tính toán trong một hội CLR . Điều này sẽ cho phép bạn gọi nó trực tiếp từ TSQL. Vì vậy, bạn sẽ có thể di chuyển toàn bộ quá trình đến máy chủ cơ sở dữ liệu.
  2. Thực hiện các tính toán trực tiếp trong TSQL như những người khác đã chỉ ra, nhưng điều đó phụ thuộc vào mức độ phức tạp của chúng. Chúng có thể trở nên khó duy trì.
0 hữu ích 2 bình luận chia sẻ
1

Bạn nên sử dụng SqlBulkCopylớp được cung cấp trong .NET. Lớp học này có nghĩa là để làm những gì bạn cần.

Đoạn mã sau đây sẽ giúp bạn. Mặc dù tôi đã viết nó ngay lập tức và không được kiểm tra, nó sẽ cung cấp cho bạn và ý tưởng về cách tiến hành vấn đề này.

Sub DoBulkCopy(ByVal sourceConnectionString As String, ByVal sourceTableSelectStatement As String, ByVal destinationConnectionString As String, ByVal destinationTableName As String)
    Try
        Using sourceConnection As New SqlConnection(SourceConnectionString)
            Using sourceCommand As New SqlCommand(sourceTableSelectStatement)
                sourceCommand.CommandTimeout = 0
                sourceCommand.Connection = sourceConnection
                sourceConnection.Open()
                Using sourceReader As SqlClient.SqlDataReader = sourceCommand.ExecuteReader
                    If sourceReader.HasRows Then
                        Using destinationConnection As New SqlConnection(destinationConnectionString)
                            destinationConnection.Open()
                            Using transaction As SqlTransaction = destinationConnection.BeginTransaction
                                Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(destinationConnection, SqlBulkCopyOptions.Default, transaction)
                                    '' If the data source and the destination table have the same number of columns, and the ordinal position of each source column 
                                    '' within the data source matches the ordinal position of the corresponding destination column, the ColumnMappings collection is unnecessary. 
                                    '' However, if the column counts differ, or the ordinal positions are not consistent, you must use ColumnMappings to 
                                    '' make sure that data is copied into the correct columns.
                                    '' ** Uncomment and modify the following commented lines if necessary. **
                                    'With bulkCopy.ColumnMappings
                                    '    .Add("Column1", "Column1")
                                    'End With

                                    bulkCopy.DestinationTableName = destinationTableName
                                    bulkCopy.WriteToServer(sourceReader)
                                    transaction.Commit()
                                End Using
                            End Using
                            destinationConnection.Close()
                        End Using
                    End If
                End Using
                sourceConnection.Close()
            End Using
        End Using
    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub
1 hữu ích 0 bình luận chia sẻ
0

Đối với vấn đề của bạn về việc nó hoạt động trong một thời gian và sau đó hết thời gian, tôi đoán rằng đây là vấn đề:

Transaction = WriteConnection.BeginTransaction
    Do While Reader.Read
        WriteCommand = New SqlCommand("StoredProcedure", WriteConnection, Transaction)
        'calculate
        'set parameters
        WriteCommand.ExecuteNonQuery()
    Loop

Nói cách khác, bạn đang cập nhật lần lượt 8 triệu bản ghi của mình trong một giao dịch. Rất có thể bạn sẽ xóa nhật ký giao dịch trong cơ sở dữ liệu của mình. Nếu bạn là người duy nhất sử dụng cơ sở dữ liệu này (bạn nói rằng đó là một dự án nghiên cứu), tôi sẽ sao lưu cơ sở dữ liệu và di chuyển transaction.commit()bên trong vòng lặp của bạn hoặc loại bỏ hoàn toàn giao dịch (vì SQL Server sử dụng các giao dịch ngầm định, những điều này sẽ giống nhau). Nếu xảy ra sự cố, quá trình khôi phục của bạn là khôi phục cơ sở dữ liệu.

Khi bạn đã dập tắt xong ngọn lửa này, tôi sẽ bắt đầu học T-SQL; bạn chỉ có thể đi xa khi sử dụng sai công cụ cho công việc.

0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ .net sql server vb.net , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading