Reputation: 517
I am retrieving data from a external source. My class matches the response of the JSON. However there is an inner object inside the json. How can I remove it when I am passing it to the dynamic parameters in 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);
}
Upvotes: 4
Views: 3447
Reputation: 83
Here is a very quick way of doing it:
var dp = new DynamicParameters();
var ignoreList = "Id,DateAdded,Name,Address1".Split(","[0]).ToList();
foreach (PropertyInfo prop in myObject.GetType().GetProperties())
{
if (!ignoreList.Contains(prop.Name))
dp.Add(prop.Name, prop.GetValue(file,null));
}
Upvotes: 1
Reputation: 517
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.state);
return true;
}
return false;
}
Upvotes: 1
Reputation: 11785
I wanted to be able to send Dapper strong types rather than anonymous objects, example:
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. 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.
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.
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. 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.
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.
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.
Upvotes: 0