如何使用c#代码将大量数据插入SQL Server 2008?

时间:2014-12-09 04:09:12

标签: c# sql-server sql-server-2008

我开发了一个程序,它在一个循环中计算并插入大约4800行到SQL Server 2008.但是在插入200多行之后,它每次都被卡住并且不会插入其余的行。

现在我在循环中用insert命令编写一个文本文件,而不是插入到DB中。如果我尝试从文本日志中复制整个4800插入命令并将其粘贴到SQL Server的查询编辑器中,那么它会在1分钟内插入所有内容。我想就如何解决这个问题提出建议?我将不胜感激任何建议或帮助。

以下是我现在正在尝试的代码示例:

 strSQL = "Insert into performance Values (@Rptdate,@CP_Name, @Shortcode, @Keyword, @MO_Count, @MO_Revenue,";
 strSQL = strSQL + "@PMT_Sent_Count, @MT_Revenue, @ZMT_Sent_Count, @Infra_Revenue, @Total_MT, @UM_rev_Share, @CP_Rev_Share, ";
 strSQL = strSQL + "@MCP_Rev_Share, @UM_Total_Revenue, @CP_Revenue)";

 try
 {
     db.openconn("MOMT_Report", "Report");
     cmd = new SqlCommand(strSQL, db.cn);

     cmd.Parameters.AddWithValue("@Rptdate", Rptdate);
     cmd.Parameters.AddWithValue("@Name", Name);
     cmd.Parameters.AddWithValue("@Shortcode", Shortcode);
     cmd.Parameters.AddWithValue("@Keyword", Keyword);
     cmd.Parameters.AddWithValue("@MO_Count", MO_Count);
     cmd.Parameters.AddWithValue("@MO_Revenue", MO_Revenue);
     cmd.Parameters.AddWithValue("@PMT_Sent_Count", PMT_Sent_Count);
     cmd.Parameters.AddWithValue("@MT_Revenue", MT_Revenue);
     cmd.Parameters.AddWithValue("@ZMT_Sent_Count", ZMT_Sent_Count);
     cmd.Parameters.AddWithValue("@Infra_Revenue", Infra_Revenue);
     cmd.Parameters.AddWithValue("@Total_MT", Total_MT);
     cmd.Parameters.AddWithValue("@rev_Share", rev_Share);
     cmd.Parameters.AddWithValue("@Rev_Share", Rev_Share);
     cmd.Parameters.AddWithValue("@MCP_Rev_Share", MCP_Rev_Share);
     cmd.Parameters.AddWithValue("@Total_Revenue", Total_Revenue);
     cmd.Parameters.AddWithValue("@Revenue", Revenue);

     cmd.CommandTimeout = 0;
     cmd.ExecuteNonQuery();
 }

6 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

我认为您需要先在下面的链接中设置超时选项:

http://msdn.microsoft.com/en-us/library/ms189470.aspx

然后尝试更改max allowed packet:

http://msdn.microsoft.com/en-us/library/ms177437.aspx

希望它能运作

答案 2 :(得分:1)

在粘贴到问题中的try块之后的某个地方是否有db.closeconn();?如果没有,那么这是一个很大的问题(即保持打开连接而不关闭它们,这可以解释为什么它在打开200多个之后冻结)。如果有一个关闭连接方法被调用那么很好,但仍然,每个INSERT打开和关闭连接是不必要的,更不用说非常低效了。

至少你可以:

  • 定义查询字符串,SqlParameterSqlCommand一次
  • 在循环中,设置参数值并调用ExecuteNonQuery();
  • (最好不要使用AddWithValue()

示例:

// this should be in a try block

strSQL = "INSERT...";
db.openconn("MOMT_Report", "Report");
cmd = new SqlCommand(strSQL, db.cn);

SqlParameter _Rptdate = new SqlParameter("@Rptdate", DbType.Int);
cmd.Parameters.Add(_Rptdate);

...{repeat for remaining params}...

// optional begin transaction

for / while loop
{
  _Rptdate.Value = Rptdate;
  // set other param values
  cmd.ExecuteNonQuery();
}

// if optional transaction was started, do commit

db.closeconn(); // this should be in a finally block

但是,插入此数据的最快和最干净的方法是使用SQL Server 2008中引入的表值参数(TVP)。您需要创建用户定义的表类型(一次)来定义结构,然后您可以在当前具有的临时插入中使用它,或者传递给存储过程。但是这样您就不需要导出到导入文件了。不需要额外的步骤。

我没有复制/粘贴大型代码块,而是注意到下面的三个链接,我已经发布了代码来执行此操作。前两个链接是完成此代码的完整代码(SQL和C#)。每个主题都略有不同(表明使用TVP的灵活性)。第三个是另一个变体,但不是完整的代码,因为它只显示前两个中的一个的差异,以适应特定的情况。但在所有3种情况下,数据从应用程序流式传输到SQL Server 。没有创建任何其他集合或外部文件;您使用当前拥有的内容,只需要一次复制单行的值即可发送。在SQL Server端,它都是作为填充的表变量而来的。这比获取内存中的数据,将其转换为文件(占用时间和磁盘空间)或XML(占用CPU和内存)或DataTable(适用于SqlBulkCopy;获取cpu和内存)要高效得多或其他什么,只依赖于文件系统等外部因素(文件需要清理,对吗?)或者需要解析XML。

答案 3 :(得分:1)

执行一个sqlcommand比执行4800 sqlcommands要好得多 有几种方法, 对于批量插入,您需要从数据库服务器访问 .txt 文件(将文件传输到数据库服务器或者可以通过网络访问该文件) 之后使用:

BULK INSERT Your_table
FROM 'full_file_name'
WITH
 (
    FIELDTERMINATOR =' terminator character',
    ROWTERMINATOR = ':\n'
  );

另一种方式:您可以在C#代码中构建一个新文本,该代码具有每行的插入命令并执行整个文本一次(最好将其放入事务中)

答案 4 :(得分:1)

我认为如果你需要使用XML批量插入,那么你也可以使用这种方法..

首先创建一个这样的商店程序..

CREATE PROCEDURE SP_INSERT_BULK
    @DataXML XML 
AS
BEGIN
    INSERT INTO performance
    SELECT 
        d.value('@Rptdate','varchar') AS Rptdate
        ,d.value('@Name','varchar') AS Name
        ,d.value('@Shortcode','varchar') AS Shortcode
        ,d.value('@Keyword','varchar') AS Keyword
        ,d.value('@MO_Count','varchar') AS MO_Count
        ,d.value('@MO_Revenue','varchar') AS MO_Revenue
        ,d.value('@PMT_Sent_Count','varchar') AS PMT_Sent_Count
        ,d.value('@MT_Revenue','varchar') AS MT_Revenue
        ,d.value('@ZMT_Sent_Count','varchar') AS ZMT_Sent_Count
        ,d.value('@Infra_Revenue','varchar') AS Infra_Revenue
        ,d.value('@Total_MT','varchar') AS Total_MT
        ,d.value('@rev_Share','varchar') AS rev_Share
        ,d.value('@Rev_Share','varchar') AS Rev_Share
        ,d.value('@MCP_Rev_Share','varchar') AS MCP_Rev_Share
        ,d.value('@Total_Revenue','varchar') AS Total_Revenue
        ,d.value('@Revenue','varchar') AS Revenue
    FROM @DataXML.nodes('Reports/Report') n(d)

END

以上商店程序仅供演示,您可以使用自己的逻辑进行修改

现在下一步是创建数据XML以作为参数

传递到您的商店过程
            //prepare your data xml here
            //you can use any of your logic to prepare dataxml
            string xmlstring = @"<?xml version='1.0' encoding='utf-8'?><Reports>";
            for (int i = 0; i < recordcout; i++)
            {   
                xmlstring += string.Format(@"<Report Rptdate='{0}' 
                                              Name='{1}' 
                                              Shortcode='{2}' 
                                              Keyword='{3}' 
                                              MO_Count='{4}' 
                                              MO_Revenue ='{5}' 
                                              PMT_Sent_Count='{6}' 
                                              MT_Revenue='{7}' 
                                              ZMT_Sent_Count ='{8}' 
                                              Infra_Revenue='{9}' 
                                              Total_MT='{10}' 
                                              rev_Share='{11}' 
                                              Rev_Share='{12}' 
                                              MCP_Rev_Share='{13}' 
                                              Total_Revenue='{14}' 
                                              Revenue='{15}' />");
            }
            xmlstring += "</Reports>";

现在,下一步是将此XML字符串传递给您的商店过程

using (SqlConnection dbConnection = new SqlConnection("CONNECTIONSTRING"))
            //Create database connection  
            {
                // Database command with stored - procedure  
                using (SqlCommand dbCommand =
                       new SqlCommand("SP_INSERT_BULK", dbConnection))
                {
                    // we are going to use store procedure  
                    dbCommand.CommandType = CommandType.StoredProcedure;
                    // Add input parameter and set its properties.
                    SqlParameter parameter = new SqlParameter();
                    // Store procedure parameter name  
                    parameter.ParameterName = "@DataXML";
                    // Parameter type as XML 
                    parameter.DbType = DbType.Xml;
                    parameter.Direction = ParameterDirection.Input; // Input Parameter  
                    parameter.Value = xmlstring; // XML string as parameter value  
                    // Add the parameter in Parameters collection.
                    dbCommand.Parameters.Add(parameter);
                    dbConnection.Open();
                    int intRetValue = dbCommand.ExecuteNonQuery();
                }
            }

答案 5 :(得分:1)

您应该在一次交易中完成所有这些工作。

Open DB connection.
Create command.
Begin transaction.
Start loop.
Clear parameters if added
Set parameters and execute it.
End loop.
Commit transaction.
Close DB connection.