多次插入更新解决方案的最佳解决方案

时间:2019-02-05 10:16:16

标签: npgsql

努力将C#和Npgsql理解为初学者。以下代码示例:

   // Insert some data
    using (var cmd = new NpgsqlCommand())
    {            cmd.Connection = conn;
        cmd.CommandText = "INSERT INTO data (some_field) VALUES (@p)";
        cmd.Parameters.AddWithValue("p", "Hello world");
        cmd.ExecuteNonQuery();
    }

到目前为止,不止一个以上的insert&update语句的语法很清楚:

cmd.CommandText = "INSERT INTO data (some_field) VALUES (@p);INSERT INTO data1...;INSERT into data2... and so on";

但是,应该在其中处理一条语句的循环的正确解决方案是什么。

这行不通:

// Insert some data
    using (var cmd = new NpgsqlCommand())
    {
        foreach(s in SomeStringCollectionOrWhatever)
        {
           cmd.Connection = conn;
           cmd.CommandText = "INSERT INTO data (some_field) VALUES (@p)";
           cmd.Parameters.AddWithValue("p", s);
           cmd.ExecuteNonQuery();
        }
    }

似乎这些值将被“连接”或记住。我看不到“清除”现有cmd对象的任何可能性。

我的第二个解决方案是将整个“ using”块包装到循环中。但是每个周期都会创建一个新对象。在我看来,这很丑。

那么我的问题的最佳解决方案是什么?

3 个答案:

答案 0 :(得分:0)

要有效地插入许多行,请看一下Npgsql的bulk copy feature-与您将INSERT语句串联成批处理相比,该API更适合(并且更有效)用于插入大量行。

答案 1 :(得分:0)

如果要通过更改参数值重新运行相同的SQL,可以执行以下操作:

using (var cmd = new NpgsqlCommand("INSERT INTO data (some_field) VALUES (@p)", conn))
{
    var p = new NpgsqlParameter("p", DbType.String); // Adjust DbType according to type
    cmd.Parameters.Add(p);
    cmd.Prepare();   // This is optional but will optimize the statement for repeated use

    foreach(var s in SomeStringCollectionOrWhatever)
    {
       p.Value = s;
       cmd.ExecuteNonQuery();
    }
}

答案 2 :(得分:0)

如果您需要大量的行,而性能是关键,那么我将推荐Npgsql的大容量复制功能,如@Shay所述。但是,如果您正在寻找一种无需批量复制的快速方法,我建议您使用Dapper

请考虑以下示例。

假设您有一个名为Event的类和要添加的事件列表。

List<Event> eventsToInsert = new List<Event>
{
    new Event() { EventId = 1, EventName = "Bday1" },
    new Event() { EventId = 2, EventName = "Bday2" },
    new Event() { EventId = 3, EventName = "Bday3" }
};

将列表添加到数据库的代码段如下所示。

var sqlInsert = "Insert into events( eventid, eventname ) values (@EventId, @EventName)";


using (IDbConnection conn = new NpgsqlConnection(cs))
{
    conn.Open();

    // Execute is an extension method supplied by Dapper
    // This code will add all the entries in the eventsToInsert List and match up the values based on property name. Only caveat is that the property names of the POCO should match the placeholder names in the SQL Statement.
    conn.Execute(sqlInsert, eventsToInsert);

    // If we want to retrieve the data back into the list
    List<Event> eventsAdded;

    // This Dapper extension will return an Ienumerable, so i cast it to a List.
    eventsAdded = conn.Query<Event>("Select * from events").ToList();

    foreach( var row in eventsAdded)
    {
        Console.WriteLine($"{row.EventId} {row.EventName} was added");
    }
}

-HTH