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

问题描述 投票:0回答:2

我正在从外部源检索数据。我的类与 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);
}
c# json dapper
2个回答
1
投票

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

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.state);
         return true;
   }

  return false;
}

0
投票

我希望能够发送 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
属性。

© www.soinside.com 2019 - 2024. All rights reserved.