首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C#中的批量更新

C#中的批量更新
EN

Stack Overflow用户
提问于 2013-12-17 21:43:12
回答 7查看 107.6K关注 0票数 67

为了在数据库中插入大量数据,我习惯于将所有插入信息收集到一个列表中,并将该列表转换为DataTable。然后我通过SqlBulkCopy将该列表插入到数据库中。

我将生成的列表发送到何处

LiMyList

其中包含要插入到数据库中的所有批量数据的信息

并将其传递给我的批量插入操作

代码语言:javascript
复制
InsertData(LiMyList, "MyTable");

InsertData在哪里

代码语言:javascript
复制
 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;
        }

现在我想做一个update操作,有没有什么方法可以把数据从C#.Net更新到DataBase,因为插入数据是由SqlBulkCopy完成的

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2013-12-17 21:47:02

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

示例:

代码语言:javascript
复制
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();
            }
        }
    }
}

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

票数 82
EN

Stack Overflow用户

发布于 2013-12-27 01:19:36

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

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

微软同时拥有用于合并的syntax referencearticle with examples

对于.NET片段,只需将参数类型设置为SqlDbType.Structured,并将所述参数的值设置为包含您想要更新的记录的数据表。

这种方法提供了清晰度和易于维护的优点。虽然可能有一些方法可以提供性能改进(例如将其放到临时表中,然后迭代该表),但我认为让.NET和SQL处理表传输和记录本身更新的简单性超过了这些方法。K.I.S.

票数 46
EN

Stack Overflow用户

发布于 2016-09-13 21:06:28

尝试在Nuget上使用SqlBulkTools。

免责声明:我是这个库的作者。

代码语言:javascript
复制
var bulk = new BulkOperations();
var records = GetRecordsToUpdate();

using (TransactionScope trans = new TransactionScope())
{
    using (SqlConnection conn = new SqlConnection(ConfigurationManager
    .ConnectionStrings["SqlBulkToolsTest"].ConnectionString))
    {
        bulk.Setup<MyTable>()
            .ForCollection(records)
            .WithTable("MyTable")
            .AddColumn(x => x.SomeColumn1)
            .AddColumn(x => x.SomeColumn2)
            .BulkUpdate()
            .MatchTargetOn(x => x.Identifier)
            .Commit(conn);
    }

    trans.Complete();
}  

只会更新'SomeColumn1‘和'SomeColumn2’。有关更多示例,请访问here

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20635796

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档