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

StackOverflow https://stackoverflow.com/questions/6069021

  •  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()});
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top