C#中的批量更新

Co.*_*den 58 .net c# sql-server bulk

为了在数据库中插入大量数据,我曾经将所有插入信息收集到列表中并将此列表转换为a DataTable.然后我通过将该列表插入数据库SqlBulkCopy.

我发送生成的列表
LiMyList
,其中包含我要插入数据库的所有批量数据的信息,并将其
传递给我的批量插入操作

InsertData(LiMyList, "MyTable");
Run Code Online (Sandbox Code Playgroud)

哪里InsertData

 public static void InsertData<T>(List<T> list,string TableName)
        {
                DataTable dt = new DataTable("MyTable");
                clsBulkOperation blk = new clsBulkOperation();
                dt = ConvertToDataTable(list);
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
                using (SqlBulkCopy bulkcopy = new SqlBulkCopy(ConfigurationManager.ConnectionStrings["SchoolSoulDataEntitiesForReport"].ConnectionString))
                {
                    bulkcopy.BulkCopyTimeout = 660;
                    bulkcopy.DestinationTableName = TableName;
                    bulkcopy.WriteToServer(dt);
                }
        }    

public static DataTable ConvertToDataTable<T>(IList<T> data)
        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
            DataTable table = new DataTable();
            foreach (PropertyDescriptor prop in properties)
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
            foreach (T item in data)
            {
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                table.Rows.Add(row);
            }
            return table;
        }
Run Code Online (Sandbox Code Playgroud)

现在我想做一个更新操作,是否有任何方法可以通过将数据SqlBulkCopy更新到DataBase从C#.Net 完成插入数据

Gui*_*rez 70

之前我所做的是从数据执行批量插入到临时表,然后使用命令或存储过程来更新临时表与目标表相关的数据.临时表是一个额外的步骤,但与逐行更新数据相比,如果行数很大,则可以通过批量插入和大量更新获得性能提升.

例:

public static void UpdateData<T>(List<T> list,string TableName)
{
    DataTable dt = new DataTable("MyTable");
    dt = ConvertToDataTable(list);

    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SchoolSoulDataEntitiesForReport"].ConnectionString))
    {
        using (SqlCommand command = new SqlCommand("", conn))
        {
            try
            {
                conn.Open();

                //Creating temp table on database
                command.CommandText = "CREATE TABLE #TmpTable(...)";
                command.ExecuteNonQuery();

                //Bulk insert into temp table
                using (SqlBulkCopy bulkcopy = new SqlBulkCopy(conn))
                {
                    bulkcopy.BulkCopyTimeout = 660;
                    bulkcopy.DestinationTableName = "#TmpTable";
                    bulkcopy.WriteToServer(dt);
                    bulkcopy.Close();
                }

                // Updating destination table, and dropping temp table
                command.CommandTimeout = 300;
                command.CommandText = "UPDATE T SET ... FROM " + TableName + " T INNER JOIN #TmpTable Temp ON ...; DROP TABLE #TmpTable;";
                command.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                // Handle exception properly
            }
            finally
            {
                conn.Close();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,单个连接用于执行整个操作,以便能够在每个步骤中使用临时表,因为临时表的范围是每个连接.

  • 使用update语句中的表值参数可以安全地省略临时表: (2认同)

Loc*_*cke 37

根据我的个人经验,处理这种情况的最佳方法是使用带有a Table-Valued Parameter和a 的存储过程User-Defined Table Type.只需使用数据表的列设置类型,并将所述数据表作为参数传入SQL命令.

在存储过程中,您可以直接连接某个唯一键(如果您要更新的所有行都存在),或者 - 如果您可能遇到必须同时执行更新和插入的情况 - 请使用SQL Merge命令存储过程以处理适用的更新和插入.

Microsoft既有语法参考,也有一篇包含 Merge 示例文章.

对于.NET部分,将参数类型SqlDbType.Structured设置为as 并将所述参数的值设置为包含要更新的记录的数据表是一件简单的事情.

该方法提供了清晰度和易维护性的优点.虽然可能有一些方法可以提供性能改进(例如将其放入临时表中然后遍历该表),但我认为它们被.NET和SQL处理传输表并更新记录本身的简单性所取代.吻

  • 你的答案被低估了.MSDN甚至通过表值参数提供批量更新的exmaples:http://msdn.microsoft.com/en-us/library/bb675163(v = vs.110).aspx (9认同)

小智 5

批量更新:

步骤1:将要更新的数据和主键放在一个列表中。

第二步:将这个列表和ConnectionString传递给BulkUpdate方法如下图

例子:

         //Method for Bulk Update the Data
    public static void BulkUpdateData<T>(List<T> list, string connetionString)
    {

        DataTable dt = new DataTable("MyTable");
        dt = ConvertToDataTable(list);

        using (SqlConnection conn = new SqlConnection(connetionString))
        {
            using (SqlCommand command = new SqlCommand("CREATE TABLE 
                  #TmpTable([PrimaryKey],[ColumnToUpdate])", conn))
            {
                try
                {
                    conn.Open();
                    command.ExecuteNonQuery();

                    using (SqlBulkCopy bulkcopy = new SqlBulkCopy(conn))
                    {
                        bulkcopy.BulkCopyTimeout = 6600;
                        bulkcopy.DestinationTableName = "#TmpTable";
                        bulkcopy.WriteToServer(dt);
                        bulkcopy.Close();
                    }


                    command.CommandTimeout = 3000;
                    command.CommandText = "UPDATE P SET P.[ColumnToUpdate]= T.[ColumnToUpdate] FROM [TableName Where you want to update ] AS P INNER JOIN #TmpTable AS T ON P.[PrimaryKey] = T.[PrimaryKey] ;DROP TABLE #TmpTable;";
                    command.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    // Handle exception properly
                }
                finally
                {
                    conn.Close();
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

步骤3:把ConvertToDataTable方法如下图。

例子:

    public static DataTable ConvertToDataTable<T>(IList<T> data)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable();
        foreach (PropertyDescriptor prop in properties)
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        foreach (T item in data)
        {
            DataRow row = table.NewRow();
            foreach (PropertyDescriptor prop in properties)
                row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
            table.Rows.Add(row);
        }
        return table;
    }
Run Code Online (Sandbox Code Playgroud)

备注:无论SquareBracket[]在哪里,放上你自己的价值。