简体   繁体   English

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

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

I am retrieving data from a external source.我正在从外部来源检索数据。 My class matches the response of the JSON.我的课程与 JSON 的响应相匹配。 However there is an inner object inside the json.但是 json 中有一个内部对象。 How can I remove it when I am passing it to the dynamic parameters in Dapper?当我将它传递给 Dapper 中的动态参数时,如何删除它?

Basic structure of the class类的基本结构

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

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

Using this like:像这样使用:

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

Still waiting for an answer, but here is the workaround I have started using仍在等待答案,但这是我开始使用的解决方法

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

I wanted to be able to send Dapper strong types rather than anonymous objects, example:我希望能够发送 Dapper 强类型而不是匿名对象,例如:

var myObject = new MyClass{
  MyProperty = 1
};

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

That works just fine, but let's say MyClass has an Id int that gets auto-incremented in the database.这工作得很好,但是假设MyClass有一个Id int 会在数据库中自动递增。 I don't need to pass it in as an argument, and I don't want to have to update my stored procedure to take a dummy id argument that won't get used.我不需要将它作为参数传递,并且我不想更新我的存储过程来获取一个不会被使用的虚拟 id 参数。

Fortunately Dapper's DynamicParameters constructor knows what to do if you give it a dictionary version of your object, so using reflection you can convert it to a dictionary, remove any fields you don't want, and then create a set of DynamicParameters from that.幸运的是,如果你给它一个字典版本的对象,Dapper 的 DynamicParameters 构造函数知道该怎么做,所以使用反射你可以将它转换为字典,删除你不需要的任何字段,然后从中创建一组 DynamicParameters。

Now the question is how to do that generically.现在的问题是如何一般地做到这一点。 If you have a lot of different entities that you want to use with Dapper, you don't want to have to convert them to dictionaries and remove the fields you don't want each time.如果您有很多不同的实体要与 Dapper 一起使用,您不希望每次都将它们转换为字典并删除不需要的字段。 You can solve that by making an attribute.你可以通过创建一个属性来解决这个问题。

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

Then decorate your class with the field(s) you want to ignore.然后用你想忽略的字段来装饰你的班级。

 public class MyClass {

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

   public int MyProperty {get; set;}
 }

Now you can create an extension method that wraps the Dapper version.现在您可以创建一个包装 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);
}

Note that you should name the method differently than the Dapper method it wraps--even though you've added a type argument--otherwise this will become the new method that is used everywhere, even with anonymous objects.请注意,您应该将该方法命名为与其包装的 Dapper 方法不同的名称——即使您添加了一个类型参数——否则这将成为到处使用的新方法,即使对于匿名对象也是如此。

Now you can do现在你可以做

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

...and it will not include the Id property that you decorated with the [DapperIgnore] attribute. ...并且它不会包含您使用 [DapperIgnore] 属性修饰的Id属性。

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

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