Есть ли встроенный класс в .Net framework, который можно использовать для обозначения AnsiString?

#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, и в большинстве случаев это любое дублирование данных.