简体   繁体   中英

Insert a list using dapper.NET C#

I'd like to insert a list of objects in an SQL table.

I know this question here but I don't understand.

Here is my class :

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

I'd like to know how could I insert my list using Dapper, I don't want to iterate on the list and save them one by one, I would like to insert all of them in one request.

You can insert these just as you would INSERT a single line:

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 will look for class members named after your SQL parameters (@Id, @ObjectType, @Content, @PreviewContent) and bind them accordingly.

You need pass a table-value parameter.
1. Create table type in your sql database.
2. Create DynamicParameters and add the datatable (new values) to it.
3. Execute.

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

More info: https://www.codeproject.com/Articles/835519/Passing-Table-Valued-Parameters-with-Dapper

You would just change your SQL to a valid insert statment that has parameters matching the names of the properties on your class.

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

Or if you need to specify the table columns (where these aren't all the columns in the table, for example):

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

You can use the Dapper.Contrib extensions to simplify the code. I've found this works well for a few hundred records, but for very large inserts, I switch to SqlBulkCopy. The synchronous version is Insert instead of InsertAsync (as you'd guess). Make sure your entities are named as Dapper expects and have a primary key, Id, or, add annotations for table name and key to your entity.

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

In case you need new naming or combined sources:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM