Dapper DynamicParameters object 可以像参数字典一样枚举吗?
Can a Dapper DynamicParameters object be enumerated like a dictionary of parameters?
我知道我可以使用 ParameterDirection
和 Dapper.DynamicParameters:
var parameters = new DynamicParameters();
parameters.Add("iparam", 42);
parameters.Add("oparam", null, DbType.Int32, ParameterDirection.Output);
connection.Execute(sql, parameters);
但是我可以在使用 Dictionary<string, object>
时这样做吗?
var parameters = new Dictionary<string, object>();
parameters.Add("iparam", 42);
parameters.Add("oparam", /* ??? */ );
connection.Execute(sql, parameters);
或者,我如何遍历 DynamicParameters
以获得参数名称和值?
原标题:
Can a Dapper parameter with ParameterDirection be added using a
dictionary?
这似乎是 Dapper 中的一个错误。这已确认在最新的 NuGet 包中工作:
foreach (var paramName in parameters.ParameterNames)
{
var value = ((SqlMapper.IParameterLookup)parameters)[paramName];
}
但是,它有点冗长。在本地使用 Dapper source (not a NuGet package), I was able to run this code without error (As of writing that's commit b77e53):
foreach (var paramName in parameters.ParameterNames)
{
var value = parameters.Get<dynamic>(paramName);
}
根据, it still throws an exception, which leads me to believe the patch hasn't made it into NuGet yet. The commit which fixes Get<dynamic>
is here
DynamicParameters
对象在每次追加时可以包含多个部分。所以像上面的答案一样遍历 ParameterNames
(它将是空的)是不够的。
public static Dictionary<string, object> ToParametersDictionary(this DynamicParameters dynamicParams)
{
var argsDictionary = new Dictionary<String, Object>();
var iLookup = (SqlMapper.IParameterLookup) dynamicParams;
//if (dynamicParams.ParameterNames.Any())
//{
// read the parameters added via dynamicParams.Add("NAME", value)
foreach (var paramName in dynamicParams.ParameterNames)
{
var value = iLookup[paramName];
argsDictionary.Add(paramName, value);
}
//}
//else
//{
// read the "templates" field containing dynamic parameters section added
// via dynamicParams.Add(new {PARAM_1 = value1, PARAM_2 = value2});
var templates = dynamicParams.GetType().GetField("templates", BindingFlags.NonPublic | BindingFlags.Instance);
if (templates != null)
{
var list = templates.GetValue(dynamicParams) as List<Object>;
if (list != null)
{
// add properties of each dynamic parameters section
foreach (var objProps in list.Select(obj => obj.GetPropertyValuePairs().ToList()))
{
objProps.ForEach(p => argsDictionary.Add(p.Key, p.Value));
}
}
}
}
return argsDictionary;
}
并且GetPropertyValuePairs(..)
是
public static Dictionary<string, object> GetPropertyValuePairs(this object obj, String[] hidden = null)
{
var type = obj.GetType();
var pairs = hidden == null
? type.GetProperties()
.DistinctBy(propertyInfo => propertyInfo.Name)
.ToDictionary(
propertyInfo => propertyInfo.Name,
propertyInfo => propertyInfo.GetValue(obj, null))
: type.GetProperties()
.Where(it => !hidden.Contains(it.Name))
.DistinctBy(propertyInfo => propertyInfo.Name)
.ToDictionary(
propertyInfo => propertyInfo.Name,
propertyInfo => propertyInfo.GetValue(obj, null));
return pairs;
}
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var seenKeys = new HashSet<TKey>();
return source.Where(element => seenKeys.Add(keySelector(element)));
}
我知道我可以使用 ParameterDirection
和 Dapper.DynamicParameters:
var parameters = new DynamicParameters();
parameters.Add("iparam", 42);
parameters.Add("oparam", null, DbType.Int32, ParameterDirection.Output);
connection.Execute(sql, parameters);
但是我可以在使用 Dictionary<string, object>
时这样做吗?
var parameters = new Dictionary<string, object>();
parameters.Add("iparam", 42);
parameters.Add("oparam", /* ??? */ );
connection.Execute(sql, parameters);
或者,我如何遍历 DynamicParameters
以获得参数名称和值?
原标题:
Can a Dapper parameter with ParameterDirection be added using a dictionary?
这似乎是 Dapper 中的一个错误。这已确认在最新的 NuGet 包中工作:
foreach (var paramName in parameters.ParameterNames)
{
var value = ((SqlMapper.IParameterLookup)parameters)[paramName];
}
但是,它有点冗长。在本地使用 Dapper source (not a NuGet package), I was able to run this code without error (As of writing that's commit b77e53):
foreach (var paramName in parameters.ParameterNames)
{
var value = parameters.Get<dynamic>(paramName);
}
根据Get<dynamic>
is here
DynamicParameters
对象在每次追加时可以包含多个部分。所以像上面的答案一样遍历 ParameterNames
(它将是空的)是不够的。
public static Dictionary<string, object> ToParametersDictionary(this DynamicParameters dynamicParams)
{
var argsDictionary = new Dictionary<String, Object>();
var iLookup = (SqlMapper.IParameterLookup) dynamicParams;
//if (dynamicParams.ParameterNames.Any())
//{
// read the parameters added via dynamicParams.Add("NAME", value)
foreach (var paramName in dynamicParams.ParameterNames)
{
var value = iLookup[paramName];
argsDictionary.Add(paramName, value);
}
//}
//else
//{
// read the "templates" field containing dynamic parameters section added
// via dynamicParams.Add(new {PARAM_1 = value1, PARAM_2 = value2});
var templates = dynamicParams.GetType().GetField("templates", BindingFlags.NonPublic | BindingFlags.Instance);
if (templates != null)
{
var list = templates.GetValue(dynamicParams) as List<Object>;
if (list != null)
{
// add properties of each dynamic parameters section
foreach (var objProps in list.Select(obj => obj.GetPropertyValuePairs().ToList()))
{
objProps.ForEach(p => argsDictionary.Add(p.Key, p.Value));
}
}
}
}
return argsDictionary;
}
并且GetPropertyValuePairs(..)
是
public static Dictionary<string, object> GetPropertyValuePairs(this object obj, String[] hidden = null)
{
var type = obj.GetType();
var pairs = hidden == null
? type.GetProperties()
.DistinctBy(propertyInfo => propertyInfo.Name)
.ToDictionary(
propertyInfo => propertyInfo.Name,
propertyInfo => propertyInfo.GetValue(obj, null))
: type.GetProperties()
.Where(it => !hidden.Contains(it.Name))
.DistinctBy(propertyInfo => propertyInfo.Name)
.ToDictionary(
propertyInfo => propertyInfo.Name,
propertyInfo => propertyInfo.GetValue(obj, null));
return pairs;
}
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var seenKeys = new HashSet<TKey>();
return source.Where(element => seenKeys.Add(keySelector(element)));
}