Is there a built-in class in the .Net framework that can be used to denote an AnsiString?
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?
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.
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()});
精彩评论