无法使用c#在循环中将数据插入SQL Server表

时间:2017-08-05 02:12:15

标签: c# sql-server

如截图所示,我试图将数据插入表格中。第一次迭代正常,但第二次迭代会抛出错误/异常。

我的代码出了什么问题?

以下是代码。

SqlConnection sqlconn = new SqlConnection(sqlconnectionstring);
//  sqlconn.Open();

string InsertData = "INSERT INTO AUStagAPITestData ([TestSuite], [TestCase],[Status], [Info], [Time], [IsArchived], [DateTime]) VALUES (@TestSuite, @TestCase, @Status, @Info, @Time, @IsArchived, @DateTime)";

SqlCommand Insertcmd = new SqlCommand(InsertData, sqlconn);

for (int j = 1; j < TDData.Length; j +=5)
{
    sqlconn.Open();

    string TestSuite = TDData[j];
    string TestCase = TDData[j+1];
    string Status = TDData[j + 2];
    string Info = TDData[j + 3];
    string Time = TDData[j + 4];

    Insertcmd.Parameters.AddWithValue("@TestSuite", TestSuite);
    Insertcmd.Parameters.AddWithValue("@TestCase", TestCase);
    Insertcmd.Parameters.AddWithValue("@Status", Status);
    Insertcmd.Parameters.AddWithValue("@Info", Info);
    Insertcmd.Parameters.AddWithValue("@Time", Time);
    Insertcmd.Parameters.AddWithValue("@IsArchived", "1");
    Insertcmd.Parameters.AddWithValue("@DateTime", DateTime.Now);

    Insertcmd.ExecuteNonQuery();
    sqlconn.Close();
}

enter image description here

6 个答案:

答案 0 :(得分:1)

它抱怨你已经添加了:

Insertcmd.Parameters.AddWithValue("@TestSuite

修复是每次迭代实例化一个新的SqlCommand

for (int j = 1; j < TDData.Length; j +=5) 
{
sqlconn.Open(); 
SqlCommand Insertcmd = new SqlCommand(InsertData, sqlconn); 
string TestSuite= TDData[j];

答案 1 :(得分:1)

真正应该做的是:

  • 在循环
  • 之前创建参数对象列表一次
  • 在循环过程中,只设置

这样的事情:

string InsertData = "INSERT INTO AUStagAPITestData ([TestSuite], [TestCase],[Status], [Info], [Time], [IsArchived], [DateTime]) VALUES (@TestSuite, @TestCase, @Status, @Info, @Time, @IsArchived, @DateTime)";

// put your connection and command into *USING* blocks to properly dispose of them
using (SqlConnection sqlconn = new SqlConnection(sqlconnectionstring))
using (SqlCommand Insertcmd = new SqlCommand(InsertData, sqlconn))
{
    // create the parameters **ONCE** and define their datatypes
    // I have only *guessed* what the datatypes could be - adapt as needed
    Insertcmd.Parameters.Add("@TestSuite", SqlDbType.VarChar, 50);
    Insertcmd.Parameters.Add("@TestCase", SqlDbType.VarChar, 50);
    Insertcmd.Parameters.Add("@Status", SqlDbType.VarChar, 50);
    Insertcmd.Parameters.Add("@Info", SqlDbType.VarChar, 50);
    Insertcmd.Parameters.Add("@Time", SqlDbType.Time);
    Insertcmd.Parameters.Add("@IsArchived", SqlDbType.Boolean);
    Insertcmd.Parameters.Add("@DateTime", SqlDbType.DateTime);

    sqlconn.Open();

    // now loop over the data and set the parameter values
    for (int j = 1; j < TDData.Length; j +=5)
    {
        string TestSuite = TDData[j];
        string TestCase = TDData[j+1];
        string Status = TDData[j + 2];
        string Info = TDData[j + 3];
        string Time = TDData[j + 4];

        Insertcmd.Parameters["@TestSuite"].Value = TestSuite;
        Insertcmd.Parameters["@TestCase"].Value = TestCase;
        Insertcmd.Parameters["@Status"].Value = Status;
        Insertcmd.Parameters["@Info"].Value = Info;
        Insertcmd.Parameters["@Time"].Value = Time;
        Insertcmd.Parameters["@IsArchived"].Value = true;
        Insertcmd.Parameters["@DateTime"].Value = DateTime.Now;

        // execute the query in the loop
        Insertcmd.ExecuteNonQuery();
    }   

    sqlconn.Close();
}

答案 2 :(得分:0)

尝试移动sqlconn.Open()&amp; sqlconn.Close()退出for循环并更新sqlcommand对象。

sqlconn.Open();
for (int j = 1; j < TDData.Length; j += 5)
{
    SqlCommand Insertcmd = new SqlCommand(InsertData, sqlconn);
    string TestSuite = TDData[j];
    ...
}
sqlconn.Close();

答案 3 :(得分:0)

根据您的代码检查此示例:

string connectionString, queryInsert;
string[] arrayData = new string[10];

connectionString = ConfigurationManager.ConnectionStrings["DbConn"].ConnectionString;
queryInsert = @"
    INSERT INTO AUStagAPITestData
    (
        [TestSuite], [TestCase], [Status], [Info], [Time], [IsArchived], [DateTime]
    )
    VALUES (
        @TestSuite, @TestCase, @Status, @Info, @Time, @IsArchived, @DateTime
    )
";

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(queryInsert, connection))
{
    string testSuite, testCase, status, info, time;

    connection.Open();

    for (int j = 1; j < arrayData.Length; j += 5)
    {
        testSuite = arrayData[j];
        testCase = arrayData[j + 1];
        status = arrayData[j + 2];
        info = arrayData[j + 3];
        time = arrayData[j + 4];

        command.Parameters.AddWithValue("@TestSuite", testSuite);
        command.Parameters.AddWithValue("@TestCase", testCase);
        command.Parameters.AddWithValue("@Status", status);
        command.Parameters.AddWithValue("@Info", info);
        command.Parameters.AddWithValue("@Time", time);
        command.Parameters.AddWithValue("@IsArchived", "1");
        command.Parameters.AddWithValue("@DateTime", DateTime.Now);

        command.ExecuteNonQuery();

        // To Clear parameters
        command.Parameters.Clear();
    }
    // no need to close a disposed object since dispose will call close 
}

答案 4 :(得分:0)

您可以在for循环中使用Insertcmd.Parameters.Clear()

答案 5 :(得分:0)

正如我在评论中所写,我将使用带有表值参数的存储过程,而不是逐个插入记录。这样做的好处是只需从应用程序代码到数据库进行一次往返 但是,它也有一个缺点 - 如果一行因任何原因失败(例如,违反约束),整个插入将失败。

话虽如此,为了使用表值参数,您应该首先创建用户定义的表类型。请注意,我在这里猜测您的列数据类型,您可能需要更改它们:

CREATE TYPE dbo.tt_TestData (
    [TestSuite] int, -- I'm guessing foreign keys
    [TestCase] int,
    [Status] int, 
    [Info] nvarchar(255), 
    [Time] time, 
    [IsArchived] bit, 
    [DateTime] datetime
);
GO

完成后,您可以创建存储过程:

CREATE PROCEDURE stp_AUStagAPITestData_Insert
(
    @Data dbo.tt_TestData READONLY -- Note: Readonly is a must!
)
AS

INSERT INTO AUStagAPITestData (
    [TestSuite], 
    [TestCase],
    [Status], 
    [Info], 
    [Time], 
    [IsArchived], 
    [DateTime]
)
SELECT 
    [TestSuite], 
    [TestCase],
    [Status], 
    [Info], 
    [Time], 
    [IsArchived], 
    [DateTime]
FROM @Data;
GO

现在,要使用ADO.Net执行此存储过程,您需要为数据创建一个数据表,并将其作为SqlDbType.Structured类型的参数传送到存储过程:

using (var sqlconn = new SqlConnection(sqlconnectionstring))
{
    using (var Insertcmd = new SqlCommand("stp_AUStagAPITestData_Insert", sqlconn))
    {
        //  Create the data table
        using (var dt = new DataTable())
        {
            dt.Columns.Add("TestSuite", typeof(int));
            dt.Columns.Add("TestCase", typeof(int));
            dt.Columns.Add("Status", typeof(int));
            dt.Columns.Add("Info", typeof(string));
            dt.Columns.Add("Time", typeof(DateTime));
            dt.Columns.Add("IsArchived", typeof(bool));
            dt.Columns.Add("DateTime", typeof(DateTime));

            // Populate the data table from the TDData string array
            for (int j = 1; j < TDData.Length; j += 5)
            {
                dt.Rows.Add
                (
                    TDData[j],      // TestSuite
                    TDData[j + 1],  // TestCase
                    TDData[j + 2],  // Status
                    TDData[j + 3],  // Info
                    TDData[j + 4],  // Time
                    true,           // IsArchived
                    DateTime.Now    // DateTime
                );
            }

            Insertcmd.CommandType = CommandType.StoredProcedure;
            Insertcmd.Parameters.Add("@Data", SqlDbType.Structured).Value = dt;

            try
            {
                sqlconn.Open();
                Insertcmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                // Exception handling code goes here...
            }
        }
    }
}