Thực hiện chèn và cập nhật với Dapper


194

Tôi quan tâm đến việc sử dụng Dapper - nhưng từ những gì tôi có thể nói thì nó chỉ hỗ trợ Truy vấn và Thực thi. Tôi không thấy rằng Dapper bao gồm một cách Chèn và Cập nhật các đối tượng.

Cho rằng dự án của chúng tôi (hầu hết các dự án?) Cần thực hiện chèn và cập nhật, cách tốt nhất để thực hiện Chèn và Cập nhật cùng với dapper là gì?

Tốt hơn là chúng ta sẽ không phải dùng đến phương pháp xây dựng tham số ADO.NET, v.v.

Câu trả lời tốt nhất tôi có thể đưa ra vào thời điểm này là sử dụng LinqToQuery để chèn và cập nhật. Có một câu trả lời tốt hơn?


3
Có phần mở rộng Contrib này từ chính Dapper.NET mà tôi sử dụng. github.com/StackExchange/dapper-dot-net/tree/master/ mẹo
Rajiv

Câu trả lời:


201

Chúng tôi đang xem xét việc xây dựng một vài người trợ giúp, vẫn quyết định API và liệu điều này có đi vào cốt lõi hay không. Xem: https://code.google.com.vn/archive/p/dapper-dot-net/issues/6 để biết tiến trình.

Trong thời gian đó bạn có thể làm như sau

val = "my value";
cnn.Execute("insert into Table(val) values (@val)", new {val});

cnn.Execute("update Table set val = @val where Id = @id", new {val, id = 1});

vân vân

Xem thêm bài viết trên blog của tôi: Đó là vấn đề INSERT gây phiền nhiễu

Cập nhật

Như đã chỉ ra trong các ý kiến, hiện tại có một số tiện ích mở rộng có sẵn trong dự án Dapper.Contrib dưới dạng các IDbConnectionphương thức mở rộng này :

T Get<T>(id);
IEnumerable<T> GetAll<T>();
int Insert<T>(T obj);
int Insert<T>(Enumerable<T> list);
bool Update<T>(T obj);
bool Update<T>(Enumerable<T> list);
bool Delete<T>(T obj);
bool Delete<T>(Enumerable<T> list);
bool DeleteAll<T>();

4
Hi Sam, tìm thấy câu trả lời SO của bạn với google và tôi đã tự hỏi nếu dòng cuối cùng của mã nên chứa từ setnhư cnn.Execute("update Table SET val = @val where Id = @id", new {val, id = 1});hoặc là đoan trang cụ thể này? Tôi chưa quen với dapper và đang tìm kiếm một ví dụ cập nhật :)
JP Hellemons

1
@JPHellemons Tôi đã thử cái này var updateCat = connection.Execute("UPDATE tCategories SET sCategory = @val WHERE iCategoryID = @id", new { val = "dapper test", id = 23 });và nó đã hoạt động. Nếu không sử dụng SET, tôi gặp lỗi cú pháp SQLException gần sC Category.
đắt tiền

3
Chuyển nhanh đến tháng 12 năm 2015: github.com/StackExchange/dapper-dot-net/tree/master/
mẹo

3
@RosdiKasim Điều này có làm thất bại mục đích sử dụng Dapper không? Tôi muốn sử dụng SQL. Điều này trừu tượng hóa nó. Tôi đang thiếu gì?
johnny

2
@johnny Đây chỉ là lớp người trợ giúp ... một số người muốn mã của họ ngắn gọn nhất có thể ... bạn không phải sử dụng nó nếu bạn không muốn.
Rosdi Kasim

67

Thực hiện các thao tác CRUD bằng Dapper là một nhiệm vụ dễ dàng. Tôi đã đề cập đến các ví dụ dưới đây sẽ giúp bạn trong các hoạt động CRUD.

Mã cho C RUD:

Phương pháp # 1: Phương pháp này được sử dụng khi bạn chèn các giá trị từ các thực thể khác nhau.

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string insertQuery = @"INSERT INTO [dbo].[Customer]([FirstName], [LastName], [State], [City], [IsActive], [CreatedOn]) VALUES (@FirstName, @LastName, @State, @City, @IsActive, @CreatedOn)";

    var result = db.Execute(insertQuery, new
    {
        customerModel.FirstName,
        customerModel.LastName,
        StateModel.State,
        CityModel.City,
        isActive,
        CreatedOn = DateTime.Now
    });
}

Phương pháp # 2: Phương thức này được sử dụng khi các thuộc tính thực thể của bạn có cùng tên với các cột SQL. Vì vậy, Dapper là một ORM ánh xạ các thuộc tính thực thể với các cột SQL phù hợp.

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string insertQuery = @"INSERT INTO [dbo].[Customer]([FirstName], [LastName], [State], [City], [IsActive], [CreatedOn]) VALUES (@FirstName, @LastName, @State, @City, @IsActive, @CreatedOn)";

    var result = db.Execute(insertQuery, customerViewModel);
}

Mã cho C R UD:

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string selectQuery = @"SELECT * FROM [dbo].[Customer] WHERE FirstName = @FirstName";

    var result = db.Query(selectQuery, new
    {
        customerModel.FirstName
    });
}

Mã cho CR U D:

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string updateQuery = @"UPDATE [dbo].[Customer] SET IsActive = @IsActive WHERE FirstName = @FirstName AND LastName = @LastName";

    var result = db.Execute(updateQuery, new
    {
        isActive,
        customerModel.FirstName,
        customerModel.LastName
    });
}

Mã cho CRU D :

using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDbConnection"].ConnectionString))
{
    string deleteQuery = @"DELETE FROM [dbo].[Customer] WHERE FirstName = @FirstName AND LastName = @LastName";

    var result = db.Execute(deleteQuery, new
    {
        customerModel.FirstName,
        customerModel.LastName
    });
}

26

bạn có thể làm theo cách như vậy:

sqlConnection.Open();

string sqlQuery = "INSERT INTO [dbo].[Customer]([FirstName],[LastName],[Address],[City]) VALUES (@FirstName,@LastName,@Address,@City)";
sqlConnection.Execute(sqlQuery,
    new
    {
        customerEntity.FirstName,
        customerEntity.LastName,
        customerEntity.Address,
        customerEntity.City
    });

sqlConnection.Close();

36
Bạn nên sử dụng using-statementđể kết nối được đóng ngay cả trong trường hợp ngoại lệ.
Tim Schmelter

12
bạn chỉ có thể truyền trực tiếp cho khách hàngEntity thay vì sử dụng một loại ẩn danh ...
Thomas Levesque

@ThomasLevesque Ý của bạn là gì? Bạn có thể cung cấp một ví dụ mã nhỏ về ý nghĩa của bạn?
iaacp

4
@iaacp, ý tôi là:sqlConnection.Execute(sqlQuery, customerEntity);
Thomas Levesque

1
@ThomasLevesque chúng ta có thể cập nhật bằng cách sử dụng cùng một mẫu không? tức là,sqlConnection.Execute(sqlQuery, customerEntity);
Shankar

16

Sử dụng Dapper.Contrib nó đơn giản như thế này:

Chèn danh sách:

public int Insert(IEnumerable<YourClass> yourClass)
{
    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        conn.Open();
        return conn.Insert(yourClass) ;
    }
}

Chèn đơn:

public int Insert(YourClass yourClass)
{
    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        conn.Open();
        return conn.Insert(yourClass) ;
    }
}

Cập nhật danh sách:

public bool Update(IEnumerable<YourClass> yourClass)
{
    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        conn.Open();
        return conn.Update(yourClass) ;
    }
}

Cập nhật đơn:

public bool Update(YourClass yourClass)
{
    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        conn.Open();
        return conn.Update(yourClass) ;
    }
}

Nguồn: https://github.com/StackExchange/Dapper/tree/master/Dapper.Contrib


1
Sử dụng cách trên để chèn một đối tượng, bạn có thể lấy lại số nhận dạng mới và đặt lại vào mô hình của mình ... Nhưng bạn làm thế nào để chèn danh sách các đối tượng - các đối tượng trong danh sách không có lĩnh vực bản sắc. Bạn có phải lặp đi lặp lại qua danh sách và sau đó chèn từng cái một, lấy ID mới ra mỗi lần không?
Harag

1
@harag Nếu bạn cần ID mới ở nơi khác tôi đoán bạn phải làm điều đó như thế. Entity Framework xử lý các loại tham chiếu, như các lớp, không có vấn đề gì với các phần chèn nhưng tôi không biết Dapper.Contrib hoạt động như thế nào nếu đó là góc của bạn.
Ogglas

5
@Ogglas, cảm ơn. Tôi đã nhận thấy "Connection.Insert (myObject)" sẽ cập nhật thuộc tính "[key]" của "myObject" nếu tôi chỉ chèn một đối tượng, nhưng nếu tôi chèn danh sách 5 đối tượng sử dụng cùng một "Connection.Insert (myObjectList)" sau đó không có thuộc tính [phím] nào được cập nhật, vì vậy tôi phải thực hiện thủ công mục trong danh sách và chèn chúng một lần.
Harag

1
Trong trường conn.Update(yourClass)hợp một số thuộc tính là null , thì CẬP NHẬT các trường thành NULL ? Không làm việc. Cập nhật trường lên NULL . Not partials updates
Kiquenet

5

Bạn cũng có thể sử dụng dapper với một thủ tục được lưu trữ và cách chung để mọi thứ dễ dàng quản lý.

Xác định kết nối của bạn:

public class Connection: IDisposable
{
    private static SqlConnectionStringBuilder ConnectionString(string dbName)
    {
        return new SqlConnectionStringBuilder
            {
                ApplicationName = "Apllication Name",
                DataSource = @"Your source",
                IntegratedSecurity = false,
                InitialCatalog = Database Name,
                Password = "Your Password",
                PersistSecurityInfo = false,
                UserID = "User Id",
                Pooling = true
            };
    }

    protected static IDbConnection LiveConnection(string dbName)
    {
        var connection = OpenConnection(ConnectionString(dbName));
        connection.Open();
        return connection;
    }

    private static IDbConnection OpenConnection(DbConnectionStringBuilder connectionString)
    {
        return new SqlConnection(connectionString.ConnectionString);
    }

    protected static bool CloseConnection(IDbConnection connection)
    {
        if (connection.State != ConnectionState.Closed)
        {
            connection.Close();
            // connection.Dispose();
        }
        return true;
    }

    private static void ClearPool()
    {
        SqlConnection.ClearAllPools();
    }

    public void Dispose()
    {
        ClearPool();
    }
}

Tạo giao diện để xác định các phương thức Dapper mà bạn thực sự cần:

 public interface IDatabaseHub
    {
   long Execute<TModel>(string storedProcedureName, TModel model, string dbName);

        /// <summary>
        /// This method is used to execute the stored procedures with parameter.This is the generic version of the method.
        /// </summary>
        /// <param name="storedProcedureName">This is the type of POCO class that will be returned. For more info, refer to https://msdn.microsoft.com/en-us/library/vstudio/dd456872(v=vs.100).aspx. </param>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="model">The model object containing all the values that passes as Stored Procedure's parameter.</param>
        /// <returns>Returns how many rows have been affected.</returns>
        Task<long> ExecuteAsync<TModel>(string storedProcedureName, TModel model, string dbName);

        /// <summary>
        /// This method is used to execute the stored procedures with parameter. This is the generic version of the method.
        /// </summary>
        /// <param name="storedProcedureName">Stored Procedure's name. Expected to be a Verbatim String, e.g. @"[Schema].[Stored-Procedure-Name]"</param>
        /// <param name="parameters">Parameter required for executing Stored Procedure.</param>        
        /// <returns>Returns how many rows have been affected.</returns>         
        long Execute(string storedProcedureName, DynamicParameters parameters, string dbName);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="storedProcedureName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        Task<long> ExecuteAsync(string storedProcedureName, DynamicParameters parameters, string dbName);
}

Thực hiện giao diện:

     public class DatabaseHub : Connection, IDatabaseHub
        {

 /// <summary>
        /// This function is used for validating if the Stored Procedure's name is correct.
        /// </summary>
        /// <param name="storedProcedureName">Stored Procedure's name. Expected to be a Verbatim String, e.g. @"[Schema].[Stored-Procedure-Name]"</param>
        /// <returns>Returns true if name is not empty and matches naming patter, otherwise returns false.</returns>

        private static bool IsStoredProcedureNameCorrect(string storedProcedureName)
        {
            if (string.IsNullOrEmpty(storedProcedureName))
            {
                return false;
            }

            if (storedProcedureName.StartsWith("[") && storedProcedureName.EndsWith("]"))
            {
                return Regex.IsMatch(storedProcedureName,
                    @"^[\[]{1}[A-Za-z0-9_]+[\]]{1}[\.]{1}[\[]{1}[A-Za-z0-9_]+[\]]{1}$");
            }
            return Regex.IsMatch(storedProcedureName, @"^[A-Za-z0-9]+[\.]{1}[A-Za-z0-9]+$");
        }

     /// <summary>
            /// This method is used to execute the stored procedures without parameter.
            /// </summary>
            /// <param name="storedProcedureName">Stored Procedure's name. Expected to be a Verbatim String, e.g. @"[Schema].[Stored-Procedure-Name]"</param>
            /// <param name="model">The model object containing all the values that passes as Stored Procedure's parameter.</param>
            /// <typeparam name="TModel">This is the type of POCO class that will be returned. For more info, refer to https://msdn.microsoft.com/en-us/library/vstudio/dd456872(v=vs.100).aspx. </typeparam>
            /// <returns>Returns how many rows have been affected.</returns>

            public long Execute<TModel>(string storedProcedureName, TModel model, string dbName)
            {
                if (!IsStoredProcedureNameCorrect(storedProcedureName))
                {
                    return 0;
                }

                using (var connection = LiveConnection(dbName))
                {
                    try
                    {
                        return connection.Execute(
                            sql: storedProcedureName,
                            param: model,
                            commandTimeout: null,
                            commandType: CommandType.StoredProcedure
                            );

                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        CloseConnection(connection);
                    }
                }
            }

            public async Task<long> ExecuteAsync<TModel>(string storedProcedureName, TModel model, string dbName)
            {
                if (!IsStoredProcedureNameCorrect(storedProcedureName))
                {
                    return 0;
                }

                using (var connection = LiveConnection(dbName))
                {
                    try
                    {
                        return await connection.ExecuteAsync(
                            sql: storedProcedureName,
                            param: model,
                            commandTimeout: null,
                            commandType: CommandType.StoredProcedure
                            );

                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        CloseConnection(connection);
                    }
                }
            }

            /// <summary>
            /// This method is used to execute the stored procedures with parameter. This is the generic version of the method.
            /// </summary>
            /// <param name="storedProcedureName">Stored Procedure's name. Expected to be a Verbatim String, e.g. @"[Schema].[Stored-Procedure-Name]"</param>
            /// <param name="parameters">Parameter required for executing Stored Procedure.</param>        
            /// <returns>Returns how many rows have been affected.</returns>

            public long Execute(string storedProcedureName, DynamicParameters parameters, string dbName)
            {
                if (!IsStoredProcedureNameCorrect(storedProcedureName))
                {
                    return 0;
                }

                using (var connection = LiveConnection(dbName))
                {
                    try
                    {
                        return connection.Execute(
                            sql: storedProcedureName,
                            param: parameters,
                            commandTimeout: null,
                            commandType: CommandType.StoredProcedure
                            );
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        CloseConnection(connection);
                    }
                }
            }



            public async Task<long> ExecuteAsync(string storedProcedureName, DynamicParameters parameters, string dbName)
            {
                if (!IsStoredProcedureNameCorrect(storedProcedureName))
                {
                    return 0;
                }

                using (var connection = LiveConnection(dbName))
                {
                    try
                    {
                        return await connection.ExecuteAsync(
                            sql: storedProcedureName,
                            param: parameters,
                            commandTimeout: null,
                            commandType: CommandType.StoredProcedure
                            );

                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        CloseConnection(connection);
                    }
                }
            }

    }

Bây giờ bạn có thể gọi từ mô hình theo nhu cầu của bạn:

public class DeviceDriverModel : Base
    {
 public class DeviceDriverSaveUpdate
        {
            public string DeviceVehicleId { get; set; }
            public string DeviceId { get; set; }
            public string DriverId { get; set; }
            public string PhoneNo { get; set; }
            public bool IsActive { get; set; }
            public string UserId { get; set; }
            public string HostIP { get; set; }
        }


        public Task<long> DeviceDriver_SaveUpdate(DeviceDriverSaveUpdate obj)
        {

            return DatabaseHub.ExecuteAsync(
                    storedProcedureName: "[dbo].[sp_SaveUpdate_DeviceDriver]", model: obj, dbName: AMSDB);//Database name defined in Base Class.
        }
}

Bạn cũng có thể truyền thông số:

public Task<long> DeleteFuelPriceEntryByID(string FuelPriceId, string UserId)
        {


            var parameters = new DynamicParameters();
            parameters.Add(name: "@FuelPriceId", value: FuelPriceId, dbType: DbType.Int32, direction: ParameterDirection.Input);
            parameters.Add(name: "@UserId", value: UserId, dbType: DbType.String, direction: ParameterDirection.Input);

            return DatabaseHub.ExecuteAsync(
                    storedProcedureName: @"[dbo].[sp_Delete_FuelPriceEntryByID]", parameters: parameters, dbName: AMSDB);

        }

Bây giờ gọi từ bộ điều khiển của bạn:

var queryData = new DeviceDriverModel().DeviceInfo_Save(obj);

Hy vọng nó ngăn chặn sự lặp lại mã của bạn và cung cấp bảo mật;


1

Bạn có thể thử điều này:

 string sql = "UPDATE Customer SET City = @City WHERE CustomerId = @CustomerId";             
 conn.Execute(sql, customerEntity);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.