Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何进行批量更新?_C#_Sql_Sql Server_Linq To Sql - Fatal编程技术网

C# 如何进行批量更新?

C# 如何进行批量更新?,c#,sql,sql-server,linq-to-sql,C#,Sql,Sql Server,Linq To Sql,我想知道有没有办法进行批量更新?我正在使用ms sql server 2005 我看到了SQLDataAdapter,但似乎您必须首先使用它来选择语句,然后填充一些数据集并对数据集进行更改 现在我使用LINQtoSQL进行选择,所以我想尽量保持这种方式。但是,它的速度太慢,无法进行大规模更新。那么,我是否可以保留我的linq到sql(对于select部分),但使用不同的东西来进行大规模更新 谢谢 编辑 我对这种暂存表的方式很感兴趣,但我不确定如何做,也不清楚它将如何更快,因为我不了解更新部分是如

我想知道有没有办法进行批量更新?我正在使用ms sql server 2005

我看到了SQLDataAdapter,但似乎您必须首先使用它来选择语句,然后填充一些数据集并对数据集进行更改

现在我使用LINQtoSQL进行选择,所以我想尽量保持这种方式。但是,它的速度太慢,无法进行大规模更新。那么,我是否可以保留我的linq到sql(对于select部分),但使用不同的东西来进行大规模更新

谢谢

编辑

我对这种暂存表的方式很感兴趣,但我不确定如何做,也不清楚它将如何更快,因为我不了解更新部分是如何工作的

有人能告诉我这是如何工作的,以及如何处理并发连接吗

Edit2

这是我尝试使用xml进行大规模更新的最新尝试,但是它占用了大量资源,而且我的共享主机不允许它通过。所以我需要一种不同的方式,这就是为什么我不去看一张临时手术台

using (TestDataContext db = new TestDataContext())
            {
                UserTable[] testRecords = new UserTable[2];
                for (int count = 0; count < 2; count++)
                {
                    UserTable testRecord = new UserTable();

                    if (count == 1)
                    {
                        testRecord.CreateDate = new DateTime(2050, 5, 10);
                        testRecord.AnotherField = true;
                    }
                    else
                    {
                        testRecord.CreateDate = new DateTime(2015, 5, 10);
                        testRecord.AnotherField = false;
                    }


                    testRecords[count] = testRecord;
                }

                StringBuilder sBuilder = new StringBuilder();
                System.IO.StringWriter sWriter = new System.IO.StringWriter(sBuilder);
                XmlSerializer serializer = new XmlSerializer(typeof(UserTable[]));
                serializer.Serialize(sWriter, testRecords);             

                using (SqlConnection con = new SqlConnection(connectionString))
                {
                    string sprocName = "spTEST_UpdateTEST_TEST";

                    using (SqlCommand cmd = new SqlCommand(sprocName, con))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.CommandType = System.Data.CommandType.StoredProcedure;

                        SqlParameter param1 = new SqlParameter("@UpdatedProdData", SqlDbType.VarChar, int.MaxValue);
                        param1.Value = sBuilder.Remove(0, 41).ToString();
                        cmd.Parameters.Add(param1);
                        con.Open();
                        int result = cmd.ExecuteNonQuery();
                        con.Close();
                    }
                }
            }

您必须直接使用表达式树,但这是可行的。事实上,它已经为您完成了,您只需下载源代码:


另一种方法是只使用存储过程或特别的SQL查询,使用
DataContext
ExecuteMethodCall
ExecuteCommand
方法使用SqlBulkCopy,它的速度非常快。您将需要一个自定义IDataReader实现,它枚举linq查询结果。查看更多信息和一些可能适用的IDataReader代码。

您可以使用sqlDataAdapter进行批量更新。如何填充数据集并不重要。L2SQL或其他什么,您可以使用不同的方法进行更新。只需使用datatable中的数据定义要运行的查询

这里的关键是UpdateBatchSize。dataadapter将以您定义的任何大小批量发送更新。您需要使用此值来查看哪个数字最有效,但通常500-1000的数字效果最好。然后,SQL可以优化更新并加快执行速度。请注意,在执行批处理更新时,不能更新datatable的行源

我使用这个方法来更新10-100K,它通常在2分钟内运行。这将取决于您正在更新的内容

对不起,这是VB

Using da As New SqlDataAdapter
      da.UpdateCommand = conn.CreateCommand
      da.UpdateCommand.CommandTimeout = 300

      da.AcceptChangesDuringUpdate = False
      da.ContinueUpdateOnError = False
      da.UpdateBatchSize = 1000 ‘Expirement for best preformance
      da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 'Needed if UpdateBatchSize > 1
      sql = "UPDATE YourTable"
      sql += " SET YourField = @YourField"
      sql += " WHERE ID = @ID"
      da.UpdateCommand.CommandText = sql
      da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None
      da.UpdateCommand.Parameters.Clear()
      da.UpdateCommand.Parameters.Add("@YourField", SqlDbType.SmallDateTime).SourceColumn = "YourField"
      da.UpdateCommand.Parameters.Add("@ID", SqlDbType.SmallDateTime).SourceColumn = "ID"

      da.Update(ds.Tables("YourTable”)
End Using

另一个选项是批量复制到临时表,然后运行查询以从中更新主表。这可能会更快。

正如allonym所说,使用SqlBulkCopy,速度非常快(我发现速度提高了200倍——从1500秒提高到6秒)。但是,您可以使用DataTable和DataRows类向SQlBulkCopy提供数据(这似乎更容易)。以这种方式使用SqlBulkCopy还具有与.NET 3.0兼容的额外优势(Linq仅在3.5中添加)。

签出一些示例代码。

即使以手动/编程方式(从任何其他源的linq)填充数据表,也可以使用SqlDataAdapter执行批处理更新


只需记住为数据表中的行手动设置
RowState
。使用
dataRow.SetModified()
进行此操作。

您能解释/证明您的评论吗。LINQ到SQL更新的性能问题?基本上归结到这一点。我想插入500条记录并更新500条记录。验证耗时1分钟58秒,使用大容量复制插入耗时2秒,使用linq to sql更新所有500行并插入它们耗时4分钟。我想把它写下来,因为我可能需要更新30000到50000行。但是,我不想使用linq到sql来执行选择和操作,因为我发现使用对象更容易。我不在乎什么时候更新它看起来是什么样子,因为如果我处理了所有记录,我应该很容易,我可以用for循环提取每个linq对象的值,并将其放入所需的内容中。非常有趣的是,你看到了使用L2S的这种性能命中。可能是由于自动同步设置导致更新需要很长时间。您是否已使用SQL Profiler查看更新过程中发生的情况?如果您在每个update语句后都看到类似select语句的内容,那么我会尝试更改Linq to SQL对象上的自动同步属性。@chobo2:您能提供几行代码来说明您的问题吗?据我所知,您正在将大约500行从SQL server下载到DataTable中,然后希望在客户端上更新该数据,然后将这些更改提交到SQL server中。对吗无论如何,您可以只跟踪更改,然后用一个命令将其发送到数据库:“开始事务\r\n更新表集column1=value1,其中id=123\r\n更新表集column2=value2,其中id=456\r\n提交事务”您能解释一下这个备选方案吗?我不关心更新部分是否在SP或ado.net中,我只关心到这一点,而是在linq to sql中进行选择和操作,以便处理对象。在我操作完它们之后,我不在乎它们是如何更新到数据库中的。@chobo2:我不确定有什么需要解释的-如果您可以将更新逻辑作为存储过程完全写在服务器上,那么只需将该SP拖到Linq to SQL设计器界面中并运行它即可。但是,如果您试图对一千条记录进行不同的更新,则不会帮助您逐个记录;加快该过程的唯一方法是使用表值参数,或批量插入到暂存表中,Linq to SQL都不支持这两种方法。@chobo2:创建一个结构与要更新的表相似的永久表,使用
SqlBulkCopy
bcp
工具批量插入更新的记录,然后运行一个存储过程,从暂存表t执行
合并
Using da As New SqlDataAdapter
      da.UpdateCommand = conn.CreateCommand
      da.UpdateCommand.CommandTimeout = 300

      da.AcceptChangesDuringUpdate = False
      da.ContinueUpdateOnError = False
      da.UpdateBatchSize = 1000 ‘Expirement for best preformance
      da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 'Needed if UpdateBatchSize > 1
      sql = "UPDATE YourTable"
      sql += " SET YourField = @YourField"
      sql += " WHERE ID = @ID"
      da.UpdateCommand.CommandText = sql
      da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None
      da.UpdateCommand.Parameters.Clear()
      da.UpdateCommand.Parameters.Add("@YourField", SqlDbType.SmallDateTime).SourceColumn = "YourField"
      da.UpdateCommand.Parameters.Add("@ID", SqlDbType.SmallDateTime).SourceColumn = "ID"

      da.Update(ds.Tables("YourTable”)
End Using