7

I have some function whose prototype looks kind of like this: public void doThings(string sql, dynamic dParams);

It does some kind of SQL querying with those parameters. I didn't write it but I have to use it. It works fine when I do something like this:

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

But not when I first put the dynamic params into an ExpandoObject:

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

The query then returns no results. I don't want to call doThings() and write that new block ten times for ten different scenarios where I might want to query for myval2 or myval3 and so on. Is there some special way I should be passing the ExpandoObject, or some other way I should be doing this in general?

idlackage
  • 2,715
  • 8
  • 31
  • 52

3 Answers3

5

Dapper doesn't support Expandos by default, but you can pass the expando to the constructor of a Dictionary<string,object> and then pass that as the dynamic argument.

Michael B
  • 7,512
  • 3
  • 31
  • 57
4

As @Michael B has mentioned, Dapper does not support Expandos as params.

If you need to build your parameters set on the fly, according to this article, you can use DynamicParameters.

Thus, you can build a translator from dynParams to DynamicParameters, and it would look something like:

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

It think it could be a nice feature.

Aryéh Radlé
  • 1,310
  • 14
  • 31
1

It looks like doThings is using reflection to get needed values, when you write:

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

you are creating type with two properties v1 and v2, but when you are using ExpandoObject your doesn't add any new properties to ExpandoObject (all its magic behavior is a compiler generated stuff).

If you want to use doThing with properties known at compile time, I understand that there is no problem. When properties are known at runtime the only way I can think about is to generate required anonymous type at runtime using Reflection.Emit. Look at this article.

csharpfolk
  • 4,124
  • 25
  • 31