首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Winform 框架通用導入導出模塊事務優化:解決 SQLite 批量寫入效能瓶頸與事務中查詢鎖表問題

     編輯:關於.NET

框架通用 Excel 導入模塊長期服務於 SQL Server,但隨 SQLite 單機版應用增多,逐條自動提交事務導致萬條數據寫入極慢。本文實現 事務性批量導入,並攻克事務中「查詢判斷是否存在」導致鎖表超時的難題,提速數十倍。

1. 事務代理事件設計

基類 FrmImportExcelData 定義兩個委托事件,將事務創建與單行保存邏輯外置給調用者:

public delegate bool SaveDataHandler(DataRow dr, DbTransaction trans);
public delegate DbTransaction CreateTransactionHandler();

public event SaveDataHandler OnDataSave;
public event CreateTransactionHandler OnCreateTransaction;

2. 批量導入主流程

if (OnCreateTransaction != null) transaction = OnCreateTransaction();
foreach (DataRow dr in dt.Rows) {
    if (OnDataSave != null) {
        bool success = OnDataSave(dr, transaction);
        if (success) itemCount++;
    }
    worker.ReportProgress(...);
}
if (transaction != null) transaction.Commit();

3. 調用者實現:事務創建與單行 Upsert

private void btnImport_Click(...) {
    var dlg = new FrmImportExcelData();
    dlg.OnDataSave += ExcelData_OnDataSave;
    dlg.OnCreateTransaction += dlg_OnCreateTransaction;
    dlg.OnRefreshData += ExcelData_OnRefreshData;
    dlg.ShowDialog();
}

DbTransaction dlg_OnCreateTransaction() => BLLFactory<DrugDetail>.Instance.CreateTransaction();

bool ExcelData_OnDataSave(DataRow dr, DbTransaction trans) {
    string drugNo = dr["藥品編碼"].ToString();
    string drugName = dr["藥品名稱"].ToString();
    if (string.IsNullOrEmpty(drugNo) && string.IsNullOrEmpty(drugName)) return false;

    var info = new DrugDetailInfo { DrugNo = drugNo, DrugName = drugName, ... };
    return BLLFactory<DrugDetail>.Instance.Insert(info, trans); // 統一事務
}

4. 關鍵難點:事務中查詢判斷存在性 (Upsert 邏輯)

錯誤做法:直接 `SELECT ...` 會因事務鎖表導致超時。
正確做法:使用 事務連接對象 執行查詢,框架基類所有查詢接口均新增 `DbTransaction trans = null` 參數:

bool dlg_OnDataSave(DataRow dr, DbTransaction trans) {
    string model = dr["裝備型號"].ToString();
    if (string.IsNullOrEmpty(model)) return false;

    // 關鍵:傳入 trans 參數,使用事務連接查詢
    var info = BLLFactory<PlaneModel>.Instance.FindSingle($"PlaneModel='{model}'", trans);
    if (info != null) {
        info.PlaneNote = dr["保障特點"].ToString(); ...
        return BLLFactory<PlaneModel>.Instance.Update(info, info.ID, trans);
    } else {
        info = new PlaneModelInfo { PlaneModel = model, ... };
        return BLLFactory<PlaneModel>.Instance.Insert(info, trans);
    }
}

5. 框架基類接口全面支援事務參數

// IDAL 接口
int GetRecordCount(string condition, DbTransaction trans = null);
bool IsExistRecord(string condition, DbTransaction trans = null);
bool IsExistKey(Hashtable table, DbTransaction trans = null);
T FindSingle(string condition, DbTransaction trans = null);

// BLL 基類實現
public virtual bool Insert(T obj, DbTransaction trans = null) => baseDal.Insert(obj, trans);
public virtual bool Update(T obj, object pk, DbTransaction trans = null) => baseDal.Update(obj, pk, trans);

此優化使 SQLite 批量導入從「不可忍受」變為「秒級完成」,並保持代碼結構清晰、事務邊界可控。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved