#c# #.net #system.data
#c# #.net #system.data
Вопрос:
Для dapper мне нужно создать поддержку для передачи параметров AnsiString.
Базы данных содержат как строки в юникоде, так и не в юникоде, поэтому выбор правильного типа параметра иногда имеет решающее значение.
DbType.String
vs 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.Данные или BCL.
Есть ли где-нибудь в BCL тип, который System.Data
я мог бы использовать в качестве контейнера для AnsiString
, с семантикой, аналогичной приведенному выше образцу?
Комментарии:
1. также … если кому-то интересно, почему отправка вопросов в последний день заняла больше секунды, вот причина 🙂
Ответ №1:
В 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);
}
Итак; он поддерживает:
- ansi против unicode
- фиксированная или динамическая длина
- в случае динамической длины, явно или неявно (4000, если длина <= 4000; в противном случае «max» — это сохраняет количество планов запросов нормальным)
Этот тип доступен внутри dapper.
Комментарии:
1. А DbString — это ваш собственный класс?
2. @zespri — да, извините; я сделаю это более явным. Сэм на самом деле спрашивал в контексте «dapper», который
DbString
сейчас находится там/3. @ Marc Gravell: да, спасибо, я понял контекст dapper, просто в вопросе Sam искал существующий класс BCL, поэтому я хотел уточнить это. Теперь с этим все ясно, спасибо.
Ответ №2:
Я думаю, вы можете использовать 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()});
Комментарии:
1. мы рассмотрели это, но в конечном счете в a
char[]
нет ничего особенного ANSI, и в большинстве случаев это любое дублирование данных.