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

Для dapper мне нужно создать поддержку для передачи параметров AnsiString.

В базах данных есть строки как в Unicode, так и в строках, отличных от Unicode, поэтому выбор правильного типа параметра иногда имеет решающее значение.

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, с семантикой, похожей на пример выше?


person Sam Saffron    schedule 20.05.2011    source источник
comment
также ... если кому-то интересно, почему в последний день отправка вопросов заняла больше секунды, вот причина :)   -  person Sam Saffron    schedule 20.05.2011


Ответы (2)


В 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; «макс.» в противном случае - это сохраняет количество планов запросов в здравом уме)

Этот тип доступен внутри dapper.

person Marc Gravell    schedule 20.05.2011
comment
А DbString — это ваш собственный класс? - person Andrew Savinykh; 20.05.2011
comment
@zespri - да, извините; Я сделаю это более явным. На самом деле Сэм спрашивал в контексте dapper, где сейчас находится DbString/ - person Marc Gravell; 20.05.2011
comment
@ Марк Гравелл: да, спасибо, я понял щеголеватый контекст, просто в вопросе Сэм искал существующий класс BCL, поэтому я хотел уточнить это. Теперь все понятно, спасибо. - person Andrew Savinykh; 20.05.2011

Думаю, вы можете использовать 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()});
person TcKs    schedule 20.05.2011
comment
мы рассмотрели это, но, в конечном счете, в char[] нет ничего особенного ANSI, и в большинстве случаев это дублирование данных в любом случае. - person Marc Gravell; 20.05.2011