Есть ли в платформе .Net встроенный класс, который можно использовать для обозначения AnsiString?
-
07-09-2020 - |
Вопрос
Для dapper мне нужно создать поддержку передачи параметров AnsiString.
В базах данных есть строки как с поддержкой Юникода, так и без него, поэтому выбор правильного типа параметра иногда имеет решающее значение.
DbType.String
против DbType.AnsiString
для определенного параметра может сильно повлиять на производительность.
В dapper мы передаем параметры динамически, например:
Query<User>("select * from Users where Name=@Name", new {Name = "name"});
У меня есть внутренняя карта, которая говорит, что если я увижу typeof(String)
Я знаю, что нужно передать параметр как DbType.String
Однако я бы хотел, чтобы мои пользователи могли указать, что строка должна быть AnsiString.Атрибуты анонимных классов не поддерживаются, поэтому для этого мне нужен отдельный тип.
Очевидно, я могу придумать один:
public class AnsiString
{
private readonly string str;
public AnsiString(string str)
{
this.str = str;
}
public String Value { get { return str; } }
}
Это дало бы мне чистый API:
Query<User>("select * from Users where Name=@Name",
new {Name = new AnsiString("name")});
Однако зачем его изобретать, если такой класс существует в System.Data или BCL.
Есть ли тип где-нибудь в BCL или System.Data
Я мог бы использовать в качестве контейнера для AnsiString
, с семантикой, аналогичной приведенному выше образцу?
Решение
В BCL или System.Data такого класса нет, придется накатить свой.
Мы выбрали пользовательский тип, чтобы в конечном итоге обеспечить более детальную настройку;этот тест показывает типичное использование:
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);
}
Так;он поддерживает:
- Анси против Юникод
- фиксированная и динамическая длина
- в случае динамической длины — явная или неявная (4000, если длина <= 4000;в противном случае «макс» — это сохраняет разумное количество планов запросов)
Тип доступен внутри щеголеватый.
Другие советы
Я думаю, ты можешь использовать string
для DbType.String
и char[]
для DbType.AnsiString
.
Он будет очень похож на ваш текущий код:
Query<User>("select * from Users where Name=@Name", new {Name = "name".ToCharArray()});
Или, если вы хотите использовать AnsiString, вы можете создать метод расширения. .ToAnsiString()
:
public static AnsiString( this string s ) { return new AnsiString(s); }
Query<User>("select * from Users where Name=@Name", new {Name = "name".ToAnsiString()});