Dapper DynamicParameters 객체를 매개 변수 사전처럼 열거 할 수 있습니까?

.net-4.5 c# dapper

문제

Dapper.DynamicParameters와 함께 ParameterDirection 을 사용할 수 있다는 것을 알고 있습니다.

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 를 반복 할 수 있습니까?

원작 제목 :

사전을 사용하여 ParameterDirection의 Dapper 매개 변수를 추가 할 수 있습니까?

수락 된 답변

그것은 Dapper의 버그 인 것 같습니다. 이것은 최신 NuGet 패키지에서 작동하는 것으로 확인되었습니다.

foreach (var paramName in parameters.ParameterNames)
{
    var value = ((SqlMapper.IParameterLookup)parameters)[paramName];
}

그러나, 그것은 약간 장황하다. 로컬로 Dapper 소스 (NuGet 패키지가 아님)를 사용하여 오류없이이 코드를 실행할 수있었습니다 (작성시 b77e53 커밋).

foreach (var paramName in parameters.ParameterNames)
{
    var value = parameters.Get<dynamic>(paramName);
}

Charles Burns의 의견 에 따르면, 여전히 예외를 던져 패치가 아직 NuGet에 포함되지 않았다고 믿습니다. Get<dynamic> 을 수정 한 커밋은 여기에 있습니다.


인기 답변

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


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow