使用dapper.NET C#插入列表

12

我想在SQL表中插入一个对象列表。

我知道这个问题在这里,但我不理解。

这是我的类:

public class MyObject 
{
    public int? ID { get; set; }
    public string ObjectType { get; set; }
    public string Content { get; set; }
    public string PreviewContent { get; set; }

    public static void SaveList(List<MyObject> lst)
    {
        using (DBConnection connection = new DBConnection())
        {
            if (connection.Connection.State != ConnectionState.Open)
                connection.Connection.Open();

            connection.Connection.Execute("INSERT INTO [MyObject] VALUE()",lst);                
        }
    }
}

我想知道如何使用Dapper插入我的列表,我不想逐个迭代并保存它们,我希望在一个请求中将它们全部插入。

5个回答

23

您可以像插入单行数据一样插入这些数据:

public class MyObject 
{
    public int? ID { get; set; }
    public string ObjectType { get; set; }
    public string Content { get; set; }
    public string PreviewContent { get; set; }

    public static void SaveList(List<MyObject> lst)
    {
        using (DBConnection connection = new DBConnection())
        {
            if (connection.Connection.State != ConnectionState.Open)
                connection.Connection.Open();

            connection.Connection.Execute("INSERT INTO [MyObject] (Id, ObjectType, Content, PreviewContent) VALUES(@Id, @ObjectType, @Content, @PreviewContent)", lst);                
        }
    }
}

Dapper会查找与您的SQL参数(@Id,@ObjectType,@Content,@PreviewContent)命名相同的类成员,并进行绑定。


它能运行,但对于1000个对象来说,仍然很慢,和我使用迭代遍历列表并逐一保存它们时的情况完全一样 :/ - Vincent Ducroquet
2
尝试使用此答案以查看是否有助于性能:https://dev59.com/42gv5IYBdhLWcg3wTvLL#12609410。顺便问候一下,好久不见 :) - Pierre-Loup Pagniez
2
这会为列表中的每个项目创建一个请求,因此无法解决问题。 - Ykok

1
你需要传递一个表值参数。 1. 在你的SQL数据库中创建表类型。 2. 创建DynamicParameters并将数据表(新值)添加到其中。 3. 执行。
SQL:
CREATE TYPE [dbo].[tvMyObjects] AS TABLE(
    [ID] INT,
    [ObjectType] [varchar](70), /*Length on your table*/
    [Content] [varchar](70), /*Length on your table*/
    [PreviewContent] [varchar](70) /*Length on your table*/
)

C#:
var dynamicParameters = new DynamicParameters();
dynamicParameters.Add("@MyObjects", lst
    .AsTableValuedParameter("dbo.tvMyObjects", new[] 
    {
        "ID" ,
        "ObjectType",
        "Content", 
        "PreviewContent"
    }));

connection.Connection.Execute(@"
    INSERT INTO [MyObject] (Id, ObjectType, Content, PreviewContent) 
    SELECT Id,
           ObjectType,
           Content,
           PreviewContent
    FROM   @MyObjects", dynamicParameters);

更多信息:https://www.codeproject.com/Articles/835519/Passing-Table-Valued-Parameters-with-Dapper


1
lst是什么?它是List<classObject>还是datatable? - LearningPal
lst是List<classObject>(来自问题)。AsTableValuedParameter函数将列表转换为数据表(https://www.codeproject.com/Articles/835519/Passing-Table-Valued-Parameters-with-Dapper)。 - Daniel Tshuva

0
你可以使用Dapper.Contrib扩展来简化代码。我发现这对于几百条记录非常有效,但对于非常大的插入操作,我会切换到SqlBulkCopy。同步版本是Insert而不是InsertAsync(正如你所猜测的那样)。确保你的实体按照Dapper的要求命名并且有一个主键Id,或者为你的实体添加表名和键的注释。
using using Dapper.Contrib.Extensions; //Git

public async Task SaveChangesAsync(IList<MyEntity> myEntityValues)
{
     var conn = new SqlConnection(myconnectionString);
     if(conn.State != ConnectionState.Open)
         conn.Open();
     await conn.InsertAsync(myEntityValues);
     if (conn.State != ConnectionState.Closed)
     {
        conn.Close();
        conn.Dispose();
      }
}

1
虽然这段代码可以工作,但最好在using语句中实例化连接,或将其包装在using块中,以确保正确关闭和处理。 - Patrick Tucci

0
你只需要将你的 SQL 更改成一个有效的插入语句,该语句具有与你的类属性名称匹配的参数。
INSERT INTO MyObject VALUES(@Id, @ObjectType, @Content, @PreviewContent)

或者如果您需要指定表格列(例如,这些不是表格中的所有列):

INSERT INTO MyObject (Id, ObjectType, Content, PreviewContent)
VALUES(@Id, @ObjectType, @Content, @PreviewContent)

问题是关于批量将列表插入到数据库中,而不是在C#代码中使用循环。 - Daniel Tshuva
@DanielTshuva 这与被接受的答案相同吗? - Charles Mager

0

如果您需要新的命名或组合来源:

await connection.ExecuteAsyncWithRetry(SqlSave,
     list.Select(x => 
            new
            {
                x.ID,
                SomeNew = NewSource.SomeNew,  // From other source
                NameNew = x.NameOld,  // New naming
                x.ObjectType,
                x.Content,
                x.ContentList = String.Join(",", x.Content)  // Data transform
            }));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接