深入理解DynamicParameters

发布时间:2023-05-18

在进行数据库操作时,我们经常需要对多个参数进行拼装,尤其是在动态查询语句中,这项工作会更加繁琐和复杂。这时DynamicParameters就能派上用场了。DynamicParameters是Dapper中的一个类,它能够帮助我们轻松地构造参数,减少冗余代码的编写,提高代码的可读性。

一、DynamicParameters的节点

DynamicParameters类位于Dapper命名空间下,我们需要在代码中引入using Dapper;才能使用它。使用DynamicParameters,最基本的就是设置参数。我们可以通过以下代码来设置参数:

DynamicParameters parameters = new DynamicParameters();
parameters.Add("userId", 1);
parameters.Add("userName", "admin");
parameters.Add("age", null);
parameters.Add("enable", true);

其中,Add方法的第一个参数是参数名,第二个参数是参数值。如果是空值,可以将参数值传递为null,如果是布尔类型,也可以直接传递truefalse。如果我们需要手动指定一个参数的类型,可以使用Add方法的第三个参数:

DynamicParameters parameters = new DynamicParameters();
parameters.Add("userId", 1, DbType.Int32);
parameters.Add("userName", "admin", DbType.String);
parameters.Add("age", null, DbType.Int32);
parameters.Add("enable", true, DbType.Boolean);

在这个例子中,我们将userId参数指定为Int32类型,userName参数指定为字符串类型,age参数指定为Int32类型,enable参数指定为Boolean类型。但对于大多数情况来说,Dapper可以自动识别参数类型,我们不必手动指定。

二、DynamicParameters参数的类型

除了基本的参数类型,DynamicParameters还支持以下几种类型的参数:

1. 动态参数

动态参数可以用来保存一系列键值对。如果我们想要查询满足一组特定条件的数据,就可以使用动态参数。下面是一个使用动态参数查询的例子:

DynamicParameters parameters = new DynamicParameters();
parameters.AddDynamicParams(new { UserId = 1, UserName = "admin" });
var sql = "SELECT * FROM Users WHERE 1 = 1";
if (parameters != null && parameters.ParameterNames.Count() > 0)
{
    foreach (string name in parameters.ParameterNames)
    {
        sql += " AND " + name + "= @" + name;
    }
    var users = connection.Query<User>(sql, parameters);
}

在这个例子中,我们首先调用AddDynamicParams方法,将一个匿名类型对象添加到DynamicParameters实例中。然后,对于每一个参数名,我们都将其添加到查询语句的WHERE条件中,并将DynamicParameters实例传递给Query方法。最后,就可以得到我们想要的结果。我们可以将这种方式扩展到任何查询语句中,从而实现更为复杂的动态查询。

2. 支持数组参数

在查询中,我们有时需要使用数组参数。比如,我们需要查询某个部门中所有的员工信息,而部门编号是一个整型数组。Dapper支持使用数组参数,具体实现方式如下:

int[] departmentIds = { 1, 2, 3 };
var sql = "SELECT * FROM Employees WHERE DepartmentId IN @DepartmentIds";
var parameter = new DynamicParameters();
parameter.Add("DepartmentIds", departmentIds, DbType.Int32, ParameterDirection.Input);
var result = connection.Query<Employee>(sql, parameter);

在这个例子中,我们首先定义了一个整型数组departmentIds,然后在查询语句中使用IN关键字查询DepartmentId是否在departmentIds数组中。接着,我们创建了一个DynamicParameters实例,使用Add方法将数组参数DepartmentIds添加到DynamicParameters中,并指定了参数类型和方向。最后,我们可以将DynamicParameters实例传递给Query方法,得到我们想要的结果。

3. 动态参数支持DataTable类型

如果我们需要批量插入或更新数据,使用DataTable类型的数组会比较方便。Dapper提供了对DataTable类型的支持,可以将DataTable作为DynamicParameters的参数值进行传递。下面是一个使用DataTable批量插入数据的例子:

public void BulkInsert(DataTable table)
{
    using IDbConnection connection = new MySqlConnection(Configuration.GetValue<string>("ConnectionString"));
    IDbTransaction transaction = null;
    try
    {
        connection.Open();
        transaction = connection.BeginTransaction();
        connection.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS TempTable (Id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(50), Age INT)");
        connection.Execute("INSERT INTO TempTable (Id, Name, Age) VALUES(0, '', 0)");
        connection.Execute("DELETE FROM TempTable WHERE Id=0");
        using (var bulkCopy = new MySqlBulkCopy((MySqlConnection)connection, transaction))
        {
            bulkCopy.BatchSize = 1000;
            bulkCopy.DestinationTableName = "TempTable";
            foreach (DataColumn column in table.Columns)
            {
                bulkCopy.ColumnMappings.Add(column.ColumnName, column.ColumnName);
            }
            bulkCopy.WriteToServer(table);
        }
        connection.Execute("INSERT INTO Users (Name, Age) SELECT Name, Age FROM TempTable");
        transaction.Commit();
    }
    catch (Exception ex)
    {
        transaction.Rollback();
        throw ex;
    }
}

在这个例子中,我们首先定义了一个BulkInsert方法,它接受一个DataTable类型的参数table。接着,我们使用MySqlBulkCopy进行批量插入操作。首先,我们创建了一个临时表TempTable,并在其中插入一条空记录,然后删除该记录。接着,我们使用MySqlBulkCopyColumnMappings属性指定每个列名称的映射关系,并将table对象写入到数据库中。最后,我们在Users表中插入由TempTable生成的数据。如果出现异常,则回滚事务。

三、总结

DynamicParameters类可以帮助我们轻松地构造参数,减少冗余代码的编写,提高代码的可读性。除了基本的参数类型,DynamicParameters还支持动态参数、数组参数和DataTable类型的参数。它使我们能够更方便地使用Dapper进行数据库操作,并且可以帮助我们完成更为复杂和高效的操作。