Existe uma classe interna na estrutura .Net que pode ser usada para denotar um AnsiString?

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

  •  07-09-2020
  •  | 
  •  

Pergunta

Para dapper, preciso criar suporte para passar parâmetros AnsiString.

Os bancos de dados têm strings unicode e não unicode; escolher o tipo de parâmetro correto às vezes é crucial.

DbType.String contra DbType.AnsiString para um parâmetro específico pode afetar fortemente o desempenho.

No dapper, passamos parâmetros dinamicamente, por exemplo:

Query<User>("select * from Users where Name=@Name", new {Name = "name"});

Tenho um mapa interno que diz que se eu ver typeof(String) Eu sei passar o parâmetro como um DbType.String

No entanto, gostaria que meus usuários pudessem indicar que a string deveria ser um AnsiString.Os atributos não são suportados para classes anônimas, então preciso de um tipo distinto para isso.

É claro que posso inventar um:

public class AnsiString 
{
    private readonly string str;
    public AnsiString(string str)
    {
        this.str = str;
    }

    public String Value { get { return str; } }
}

O que me daria a API limpa:

Query<User>("select * from Users where Name=@Name", 
   new {Name = new AnsiString("name")});

No entanto, por que inventar uma se tal classe existe em System.Data ou na BCL.

Existe um tipo em algum lugar da BCL ou System.Data Eu poderia usar como recipiente para AnsiString, com semântica semelhante à amostra acima?

Foi útil?

Solução

Não existe tal classe no BCL ou System.Data, você terá que criar a sua própria.

Optamos por um tipo personalizado para fornecer uma personalização mais refinada no final;este teste mostra o uso típico:

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);
}

Então;ele suporta:

  • ansi versus unicode
  • comprimento fixo vs dinâmico
  • no caso de comprimento dinâmico, explícito vs implícito (4000 se o comprimento for <= 4000;"max", caso contrário - isso mantém o número de planos de consulta corretos)

O tipo está disponível dentro elegante.

Outras dicas

Eu acho que você pode usar string para DbType.String e char[] para DbType.AnsiString.

Será muito semelhante ao seu código atual:

Query<User>("select * from Users where Name=@Name", new {Name = "name".ToCharArray()});

Ou se você quiser usar seu AnsiString, você pode criar um método de extensão .ToAnsiString():

public static AnsiString( this string s ) { return new AnsiString(s); }
Query<User>("select * from Users where Name=@Name", new {Name = "name".ToAnsiString()});
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top