Передача динамических параметров с помощью ExpandoObject

У меня есть функция, прототип которой выглядит примерно так: public void doThings(string sql, dynamic dParams);

Он выполняет какой-то SQL-запрос с этими параметрами. Я не писал это, но я должен это использовать. Он отлично работает, когда я делаю что-то вроде этого:

doThings("select * from SomeTable where myval1=@v1 and myval2=@v2",
        new
        {
            v1 = new Dapper.DbString()
            {
                Value = "yay",
                IsAnsi = true,
                Length = 50
            },
            v2 = new Dapper.DbString()
            {
                Value = "really",
                IsAnsi = true,
                Length = 32
            }
        });

Но не тогда, когда я впервые поместил динамические параметры в ExpandoObject:

dynamic dynParams = new ExpandoObject();
dynParams.v1 = new Dapper.DbString()
    {
        Value = "yay",
        IsAnsi = true,
        Length = 50
    }
doThings("query here", dynParams);  

Затем запрос не возвращает никаких результатов. Я не хочу вызывать doThings() и записывать этот блок new десять раз для десяти разных сценариев, когда мне может понадобиться запросить myval2 или myval3 и так далее. Есть ли какой-то особый способ, которым я должен передавать ExpandoObject, или какой-то другой способ, которым я должен это делать в целом?


person idlackage    schedule 24.09.2013    source источник


Ответы (3)


Dapper не поддерживает Expandos по умолчанию, но вы можете передать Expando конструктору Dictionary<string,object>, а затем передать его в качестве динамического аргумента.

person Michael B    schedule 18.11.2013

Как уже упоминал @Michael B, Dapper не поддерживает Expandos в качестве параметров.

Если вам нужно настроить свои параметры на лету, в соответствии с этим статья, вы можете использовать DynamicParameters.

Таким образом, вы можете построить транслятор из dynParams в DynamicParameters, и это будет выглядеть примерно так:

dynamic dynParams = new ExpandoObject();
dynParams.v1 = new Dapper.DbString()
{
    Value = "yay",
    IsAnsi = true,
    Length = 50
};

var parameters = new Dapper.DynamicParameters();

((ExpandoObject)dynParams).ToList().ForEach(kvp => parameters.Add(kvp.Key, kvp.Value));

Думаю, это может быть хорошей функцией.

person Aryéh Radlé    schedule 25.12.2017

Похоже, что doThings использует отражение для получения необходимых значений, когда вы пишете:

new { 
    v1 = 1,
    v2 = "foo"
}

вы создаете тип с двумя свойствами v1 и v2, но когда вы используете ExpandoObject, ваш не добавляет никаких новых свойств к ExpandoObject (все его волшебное поведение - это сгенерированный компилятором материал).

Если вы хотите использовать doThing со свойствами, известными во время компиляции, я понимаю, что нет проблем. Когда свойства известны во время выполнения, единственный способ, о котором я могу думать, - это сгенерировать требуемый анонимный тип во время выполнения, используя Reflection.Emit. Ознакомьтесь с этой статьей.

person csharpfolk    schedule 24.09.2013