Existe uma classe interna na estrutura .Net que pode ser usada para denotar um AnsiString?
-
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?
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()});