繁体   English   中英

我可以从 Dapper DynamicParameters 中删除参数吗?

[英]Can I remove a parameter from the Dapper DynamicParameters?

我正在从外部来源检索数据。 我的课程与 JSON 的响应相匹配。 但是 json 中有一个内部对象。 当我将它传递给 Dapper 中的动态参数时,如何删除它?

类的基本结构

{
   "name": "John",
   ... 30 more fields here ...

   "location": {
       "city": "abcd", 
       "zip": "87123"
    }
}

像这样使用:

foreach (var result in response.results) 
{
    var parameters = new DynamicParameters();
    parameters.AddDynamicParams(result);

    // I need to remove "location" from this parameter
    // and then I can add the city and zip

    parameters.AddDynamicParams(result.location.city); // etc

    db.Execute("save_data", parameters, commandType:CommandType.StoredProcedure);
}

仍在等待答案,但这是我开始使用的解决方法

foreach (var result in response.results) {
  var parameters = new DynamicParameters();

  foreach (PropertyInfo prop in result.GetType().GetProperties()) {

      if (!SpecialParameter(result, prop, parameters))
         parameters.Add(prop.Name, prop.GetValue(result, null));

  }

  db.Execute("save_data",
         parameters, commandType: CommandType.StoredProcedure);
}    


function SpecialParameter(result, prop, parameters) {
// can be implemented in the sub class

   switch (prop.Name) {
      case "location":
         parameters.Add("location_city", result.city);
         parameters.Add("location_state", result.city);
         return true;
   }

  return false;
}

我希望能够发送 Dapper 强类型而不是匿名对象,例如:

var myObject = new MyClass{
  MyProperty = 1
};

_connection.ExecuteAsync(
  "InsertStoredProcedure",
  myObject,
  commandType: CommandType.StoredProcedure
)

这工作得很好,但是假设MyClass有一个Id int 会在数据库中自动递增。 我不需要将它作为参数传递,并且我不想更新我的存储过程来获取一个不会被使用的虚拟 id 参数。

幸运的是,如果你给它一个字典版本的对象,Dapper 的 DynamicParameters 构造函数知道该怎么做,所以使用反射你可以将它转换为字典,删除你不需要的任何字段,然后从中创建一组 DynamicParameters。

现在的问题是如何一般地做到这一点。 如果您有很多不同的实体要与 Dapper 一起使用,您不希望每次都将它们转换为字典并删除不需要的字段。 你可以通过创建一个属性来解决这个问题。

[AttributeUsage(AttributeTargets.Property)]
public class DapperIgnore : Attribute {}

然后用你想忽略的字段来装饰你的班级。

 public class MyClass {

   [DapperIgnore]
   public long Id {get; set;}

   public int MyProperty {get; set;}
 }

现在您可以创建一个包装 Dapper 版本的扩展方法。

public static async Task<int> ExecuteWithTypeAsync<TInput>(
  this IDbConnection cnn,
  string sql,
  TInput input,
  IDbTransaction transaction = null,
  int? commandTimeout commandTimeout = null,
  CommandType? commandType = null
){
   var dictionary = typeof(TInput).GetProperties()
     .Where(property => property
         .GetCustomAttributes(false)
         .All(attr => attr is not DapperIgnore)
     )
     .ToDictionary(x => x.Name, x => x.GetValue(input));

     var parameters = new DynamicParameters(dictionary);
     return await cnn.ExecuteAsync(sql, parameters, transaction, commandTimeout, commandType);
}

请注意,您应该将该方法命名为与其包装的 Dapper 方法不同的名称——即使您添加了一个类型参数——否则这将成为到处使用的新方法,即使对于匿名对象也是如此。

现在你可以做

_connection.ExecuteWithTypeAsync(
  "InsertStoredProcedure",
  myObject,
  commandType: CommandType.StoredProcedure
)

...并且它不会包含您使用 [DapperIgnore] 属性修饰的Id属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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