我正在从外部源检索数据。我的类与 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.state);
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
属性。