【问题标题】:Insert a list using dapper.NET C#使用 dapper.NET C# 插入列表
【发布时间】:2017-05-16 13:52:16
【问题描述】:

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

我知道这个问题here,但我不明白。

这是我的课:

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 插入我的列表,我不想在列表上迭代并一一保存,我想在一个请求中插入所有这些。

【问题讨论】:

    标签: c# sql list dapper


    【解决方案1】:

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

    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 个对象,它仍然很慢,当我在列表上使用迭代并一一保存时完全相同:/
    • 试试这个答案,看看它是否有助于提高性能:stackoverflow.com/a/12609410/1166719。顺便说一句,嗨!好久不见:)
    • 这会为列表中的每个项目创建一个请求,因此无法解决问题。
    【解决方案2】:

    您需要传递一个表值参数。
    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

    【讨论】:

    • 什么是 lst?是 List 吗?还是数据表?
    • lst 是 List (来自问题)。 AsTableValuedParameter 函数将列表转换为数据表 (codeproject.com/Articles/835519/…)
    【解决方案3】:

    您只需将您的 SQL 更改为一个有效的插入语句,该语句的参数与您的类的属性名称匹配。

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

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

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

    【讨论】:

    • 问题是关于将列表批量插入数据库。在 c# 代码中没有循环。
    • @DanielTshuva 这与接受的答案相同吗?
    【解决方案4】:

    您可以使用 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();
          }
    }
    

    【讨论】:

    • 虽然此代码有效,但理想情况下,它应该在 using 语句中实例化连接,或者将其包装在 using 块中,以确保它被正确关闭和处理。
    【解决方案5】:

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

    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
                }));
    

    【讨论】:

      猜你喜欢
      • 2013-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-27
      • 2015-05-05
      • 2015-07-13
      • 1970-01-01
      • 2022-06-14
      相关资源
      最近更新 更多