簡體   English   中英

如何將批量記錄作為事務更有效地保存到SQL Server?

[英]How to save bulk records as transaction to SQL server more efficiently?

我正在使用C#MVC應用程序。 在此應用程序中,用戶正在從EXCEL電子表格上傳數據,並且數據顯示在網格中。

在顯示到網格后,用戶點擊“驗證數據”按鈕。 應用程序需要執行UI(數據長度,空字段,數據格式等)驗證,此外,例如,還需要SQL驗證。 記錄應該已經不存在,任何約束等。

將驗證數據顯示給用戶后,顯示與每一行相關的任何錯誤,以便他/她可以對粘貼的數據進行更正,然后將數據作為事務保存到SQL Server數據庫中。

我想做到這一點的一種方法是,用C#代碼循環數據,並通過使用返回語句調用一些存儲過程來對每一行執行驗證,然后將相同的數據存儲在數據集中,然后在網格中顯示給用戶。 然后,當他提交時,在事務中循環執行插入語句。

問題是我正在考慮的方法會使數據庫命中次數翻倍。

因此,如果網格中有100行,則將需要200次數據庫匹配。

我正在尋求建議,是否還有另一種有效的方法可以做到這一點。

這是我的方法:

您可以在客戶端上驗證所有UI端驗證,例如長度等。這樣您就不必前往應用程序和數據庫服務器。

對於數據操作,這是我已多次實施的方法。

  1. 創建一個表類型,該表類型必須具有您需要處理的所有列。

  2. 使用該表類型變量到存儲過程中作為輸入參數,您可以在其中一次性傳遞n個行,這樣就無需在c#中循環就可以多次訪問數據庫。

  3. 存儲過程中的用戶merge語句,如果記錄不匹配,則可以插入它;如果匹配,則可以根據需要更新。 您也可以在事務內部執行此操作。

希望這會幫助你。

編輯1:根據您對數據庫級別驗證的評論。

在數據庫端將出現兩種類型的錯誤。 1.數據本身不會采用sql表定義所期望的格式,例如數據類型轉換失敗。

  1. DDL級別錯誤,例如數據長度超過或外鍵約束等。

我建議對您可以在c#級進行編碼的數據進行所有可能的驗證。 像基於目標列的數據長度。 調用存儲過程之前的數據類型,您可以在c#級別過濾此類記錄。 在此級別上,您可以進行最大程度的驗證。

將數據傳遞到sql服務器后,您可以在SQL Server中使用try and catch,在其中可以實現失敗行的邏輯。 將失敗的行保留在臨時表中,您可以稍后返回並插入所有成功的行。

編輯2:這是可能的代碼。

CREATE TABLE Users
(
    Idx             BIGINT IDENTITY(1,1),
    UserID          UNIQUEIDENTIFIER,
    FirstName       VARCHAR(100),
    LastName        VARCHAR(100),
    Email           VARCHAR(100),
    UserPassword    VARCHAR(100),
    InsertDate      DATETIME,
    UpDateDate      DATETIME,
    IsActive        BIT,
 CONSTRAINT [Users_PK] PRIMARY KEY CLUSTERED 
(
    [UserID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

CREATE TYPE UT_Users AS TABLE  
(  
    Idx             INT,
    FirstName       VARCHAR(100),
    LastName        VARCHAR(100),
    Email           VARCHAR(100),
    UserPassword    VARCHAR(100),
    InsertDate      DATETIME,
    UpDateDate      DATETIME,
    IsActive        BIT
) 
GO

CREATE PROCEDURE uspInsertUsers(@user_Details [UT_Users]) READONLY
AS  
BEGIN  
    DECLARE @Counter INT=1
    DECLARE @TotalRows INT=0

    SELECT @TotalRows = COUNT(1) FROM @user_Details

    WHILE @TotalRows>@Counter
        BEGIN  
            TRY
                BEGIN
                    INSERT INTO dbo.Users  
                    SELECT * FROM @user_Details WHERE @Counter = Idx
                END
            CATCH
                BEGIN
                    --write code for catching the error as per your need. Store row in temp tables and return the temp table at the end
                END
            SET @Counter = @Counter+1
        END  
END
GO
DECLARE @user_Details AS [UT_Users];

INSERT @user_Details
SELECT 1,'Rahul','Neekhra','rahul@india.com','12345',GETDATE(),GETDATE(),1 UNION
SELECT 2,'James','Streak','streak@usa.com','12345',GETDATE(),GETDATE(),1 

EXEC uspInsertUsers @user_Details

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM