4

For dapper I need to build support for passing in AnsiString params.

Databases have both unicode and non-unicode strings, picking the right parameter type is sometimes crucial.

DbType.String vs DbType.AnsiString for a particular param can heavily effect perf.

In dapper we pass in parameters dynamically, Eg:

Query<User>("select * from Users where Name=@Name", new {Name = "name"});

I have an internal map that says that if I see typeof(String) I know to pass in the param as a DbType.String

However, I would like my users to be able to denote that the string should be an AnsiString. Attributes are not supported for anonymous classes, so I need a distinct type for this.

Clearly I can invent one:

public class AnsiString 
{
    private readonly string str;
    public AnsiString(string str)
    {
        this.str = str;
    }

    public String Value { get { return str; } }
}

Which would give me the clean API:

Query<User>("select * from Users where Name=@Name", 
   new {Name = new AnsiString("name")});

However, why invent one if such a class exists in System.Data or the BCL.

Is there a type somewhere in the BCL or System.Data I could use as a container for AnsiString, with similar semantics to the sample above?

Sam Saffron
  • 128,308
  • 78
  • 326
  • 506
  • 1
    also ... if anyone is wondering why it took over a second to submit questions in the last day, this is the reason :) – Sam Saffron May 20 '11 at 07:57

2 Answers2

1

There is not such class in the BCL or System.Data, you will have to roll your own.

We went with a custom type to provide more fine-grained customn in the end; this test shows typical usage:

public void TestDbString()
{
    var obj = connection.Query("select datalength(@a) as a, datalength(@b) as b, datalength(@c) as c, datalength(@d) as d, datalength(@e) as e, datalength(@f) as f",
        new
        {
            a = new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = true },
            b = new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = false },
            c = new DbString { Value = "abcde", IsFixedLength = false, Length = 10, IsAnsi = true },
            d = new DbString { Value = "abcde", IsFixedLength = false, Length = 10, IsAnsi = false },
            e = new DbString { Value = "abcde", IsAnsi = true },
            f = new DbString { Value = "abcde", IsAnsi = false },
        }).First();
    ((int)obj.a).IsEqualTo(10);
    ((int)obj.b).IsEqualTo(20);
    ((int)obj.c).IsEqualTo(5);
    ((int)obj.d).IsEqualTo(10);
    ((int)obj.e).IsEqualTo(5);
    ((int)obj.f).IsEqualTo(10);
}

So; it supports:

  • ansi vs unicode
  • fixed vs dynamic length
  • in the case of dynamic length, explict vs implicit (4000 if the length is <= 4000; "max" otherwise - this keeps the number of query-plans sane)

The type is available inside dapper.

Sam Saffron
  • 128,308
  • 78
  • 326
  • 506
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • And DbString is your own class? – Andrew Savinykh May 20 '11 at 11:39
  • @zespri - yes, sorry; I'll make that more explicit. Sam was actually asking in the context of "dapper", which is where `DbString` now resides/ – Marc Gravell May 20 '11 at 11:44
  • @ Marc Gravell: yes, thank you, I understood the dapper context, it's just that in the question Sam was looking for an existing BCL class, so I wanted to clarify this. Now this is all clear, thank you. – Andrew Savinykh May 20 '11 at 13:11
0

I guess you can use string for DbType.String and char[] for DbType.AnsiString.

It will look very similar to your current code:

Query<User>("select * from Users where Name=@Name", new {Name = "name".ToCharArray()});

Or if you wan use your AnsiString, you can create extension method .ToAnsiString():

public static AnsiString( this string s ) { return new AnsiString(s); }
Query<User>("select * from Users where Name=@Name", new {Name = "name".ToAnsiString()});
TcKs
  • 25,849
  • 11
  • 66
  • 104
  • 1
    we looked at this, but ultimately there is nothing particularly ANSI about a `char[]`, and in most cases this is a duplication of the data *anyaway*. – Marc Gravell May 20 '11 at 12:28