簡體   English   中英

如何使用sql Bulkcopy在表中插入datagridview行

[英]how to use sql Bulkcopy to insert datagridview rows in table

我想將 datagridview 行插入到 sql server 表中......現在使用此代碼將來自 DataGridView 的行值插入表中:

private DataTable GetDataTableFromDGV(DataGridView dgv)
        {
            var dt = new DataTable();
            foreach (DataGridViewColumn column in dgv.Columns)
            {
                if (column.Visible)
                {
                    dt.Columns.Add();
                }
            }
            object[] cellValues = new object[dgv.Columns.Count];
            foreach (DataGridViewRow row in dgv.Rows)
            {
                for (int i = 0; i < row.Cells.Count; i++)
                {
                    cellValues[i] = row.Cells[i].Value;
                }
                dt.Rows.Add(cellValues);
            }
            return dt;
        }

        private void InsertDTtoDB(string ConnectionString, string TableName, DataGridView DGV)
        {
            DataTable dt = new DataTable();
            dt = GetDataTableFromDGV(DGV);
            using (SqlConnection cn = new SqlConnection(ConnectionString))
            {
                cn.Open();
                using (SqlBulkCopy copy = new SqlBulkCopy(cn))
                {                        
                    copy.ColumnMappings.Add(0, 1);
                    copy.ColumnMappings.Add(1, 2);
                    copy.ColumnMappings.Add(2, 3);
                    copy.ColumnMappings.Add(3, 4);
                    copy.ColumnMappings.Add(4, 5);
                    copy.DestinationTableName = TableName;
                    copy.WriteToServer(dt);
                }
            }
        }

但是插入數據時遇到問題:datatgridview 中的空行(啟用添加行)存儲在最后一個表行中! 請注意圖片幫助:

在此處輸入圖片說明 在此處輸入圖片說明

首先,一些可以幫助您更好地理解在 C# 中編寫代碼的一般觀察:

// this line is declaring a new variable named 'dt' 
// and assigning it an instance of a new DataTable
DataTable dt = new DataTable();
// this line is immediately overwriting the new DataTable 
// assigned to 'dt' with the DataTable returned from 'GetDataTableFromDGV'
dt = GetDataTableFromDGV(DGV);

上面應該寫成聲明變量然后賦值:

DataTable dt = GetDataTableFromDGV(DBV);

以下來自GetDataTableFromDGV ,僅當該列可見時才會向 DataTable 添加一列:

foreach (DataGridViewColumn column in dgv.Columns)
{
    if (column.Visible)
    {
        dt.Columns.Add();
    }
} 

然后在InsertDTtoDB中使用來自上面的 DataTable 的結果,它顯然期望在預定義的序數位置中設置一定數量的列:

copy.ColumnMappings.Add(0, 1);
// etc...

以上是在GetDataTableFromDGV中創建的 DataTable 之間創建一個非常脆弱的關系,它要求 Column 可見,然后在InsertDTtoDB

而不是在 DataTable 和 SqlBulkCopy.ColumnMappings 之間使用脆弱的序數關系,而是使用字段的名稱來創建 DataTable,然后映射到 SqlBulkCopy。 `GetDataTableFromDGV' 中的 foreach 然后變成:

// assumes the columns in the DataGridView are named as follows:
var columns = new[] {"Id", "Invoice_Id", "Software_Id", "Price", "Quantity", "Sum" }
var dt = new DataTable();
foreach (DataGridViewColumn column in dgv.Columns)
{
    // note: this is case-sensitive
    if (columns.Contains(column.Name))
    {
        dt.Columns.Add();
    }
}

然后InsertDTtoDB中的InsertDTtoDB變成:

copy.ColumnMappings.Add("Invoice_Id", "DestinationCol1");
copy.ColumnMappings.Add("Software_Id", "DestinationCol2");
// etc...

將行添加到GetDataTableFromDGV的 DataTable 時, cellValues變量在 foreach 循環外聲明,但值在內部 for 循環中不斷被覆蓋。 不是將對象數組添加到 DataTable,而是使用實際的列名來構建 DataRow 並將新的 DataRow 添加到 DataTable。

考慮到上述情況, GetDataTableFromDGV方法變為:

private DataTable GetDataTableFromDGV(DataGridView dgv)
{
    // use your actual columns names instead of Col1, Col2, etc...
    var columns = new[] {"Invoice_Id", "Software_Id", "Price", "Quantity", "Sum" }
    var dt = new DataTable();
    foreach (DataGridViewColumn column in dgv.Columns)
    {
        if (columns.Contains(column.Name))
        {
            dt.Columns.Add();
        }
    }

    foreach (DataGridViewRow row in dgv.Rows)
    {
        DataRow newRow = dt.NewRow();
        foreach (string columnName in columns)
        {
            newRow[columnName] = row.Cells[columnName].Value
        }

        dt.Rows.Add(newRow);
    }
    return dt;
}

然后InsertDTtoDB方法變為:

private void InsertDTtoDB(string ConnectionString, string TableName, DataGridView DGV)
{
    DataTable dt = GetDataTableFromDGV(DGV);
    using (SqlConnection cn = new SqlConnection(ConnectionString))
    {
        cn.Open();
        using (SqlBulkCopy copy = new SqlBulkCopy(cn))
        {   
            // update the "DestinationCol[x]" values to the destination column names
            copy.ColumnMappings.Add("Invoice_Id", "DestinationCol1");
            copy.ColumnMappings.Add("Software_Id", "DestinationCol2");
            copy.ColumnMappings.Add("Price", "DestinationCol3");
            copy.ColumnMappings.Add("Quantity", "DestinationCol4");
            copy.ColumnMappings.Add("Sum", "DestinationCol5");
            copy.DestinationTableName = TableName;
            copy.WriteToServer(dt);
        }
    }
}

要回答關於為什么將空行添加到數據庫的問題,我懷疑是因為 DataGridView 中有空值。 假設是這種情況,然后將 DataGridView 中的空值排除在添加到 DataTable 中。 我會關閉關鍵列之一,例如“Invoice_Id”; GetDataTableFromDGV方法然后變為:

private DataTable GetDataTableFromDGV(DataGridView dgv)
{
    // assumes the columns in the DataGridView are named as follows:
    var columns = new[] {"Invoice_Id", "Software_Id", "Price", "Quantity", "Sum" }
    var dt = new DataTable();
    foreach (DataGridViewColumn column in dgv.Columns)
    {
        if (columns.Contains(column.Name))
        {
            dt.Columns.Add();
        }
    }

    foreach (DataGridViewRow row in dgv.Rows)
    {
        // check if the row has a null "Invoice_Id" and exclude
        if(row.Cells["Invoice_Id"] == null
        {
            continue;
        }

        DataRow newRow = dt.NewRow();
        foreach (string columnName in columns)
        {
            newRow[columnName] = row.Cells[columnName].Value
        }

        dt.Rows.Add(newRow);
    }
    return dt;
}

暫無
暫無

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

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