Gibt es im .Net-Framework eine integrierte Klasse, die zur Bezeichnung eines AnsiStrings verwendet werden kann?
-
07-09-2020 - |
Frage
Für Dapper muss ich Unterstützung für die Übergabe von AnsiString-Parametern aufbauen.
Da Datenbanken sowohl Unicode- als auch Nicht-Unicode-Zeichenfolgen enthalten, ist die Auswahl des richtigen Parametertyps manchmal entscheidend.
DbType.String
vs DbType.AnsiString
denn ein bestimmter Parameter kann die Leistung stark beeinflussen.
In Dapper übergeben wir Parameter dynamisch, z. B.:
Query<User>("select * from Users where Name=@Name", new {Name = "name"});
Ich habe eine interne Karte, die das sagt, wenn ich es sehe typeof(String)
Ich weiß, dass ich den Parameter als a übergeben muss DbType.String
Ich möchte jedoch, dass meine Benutzer angeben können, dass die Zeichenfolge ein AnsiString sein soll.Attribute werden für anonyme Klassen nicht unterstützt, daher benötige ich hierfür einen eindeutigen Typ.
Offensichtlich kann ich eines erfinden:
public class AnsiString
{
private readonly string str;
public AnsiString(string str)
{
this.str = str;
}
public String Value { get { return str; } }
}
Was mir die saubere API geben würde:
Query<User>("select * from Users where Name=@Name",
new {Name = new AnsiString("name")});
Warum jedoch eine erfinden, wenn eine solche Klasse in System.Data oder der BCL vorhanden ist?
Gibt es irgendwo in der BCL einen Typ bzw System.Data
Ich könnte es als Behälter für verwenden AnsiString
, mit ähnlicher Semantik wie im obigen Beispiel?
Lösung
Es gibt keine solche Klasse in der BCL oder System.Data, Sie müssen Ihre eigene rollen.
Wir haben uns für einen benutzerdefinierten Typ entschieden, um letztendlich eine feinere Anpassung zu ermöglichen.Dieser Test zeigt die typische Verwendung:
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);
}
Also;es unterstützt:
- Ansi vs. Unicode
- feste vs. dynamische Länge
- bei dynamischer Länge: explizit vs. implizit (4000, wenn die Länge <= 4000 ist;andernfalls „max“ – dies hält die Anzahl der Abfragepläne im Rahmen)
Der Typ ist innen erhältlich elegant.
Andere Tipps
Ich denke, Sie können es verwenden string
für DbType.String
Und char[]
für DbType.AnsiString
.
Es wird Ihrem aktuellen Code sehr ähnlich sehen:
Query<User>("select * from Users where Name=@Name", new {Name = "name".ToCharArray()});
Wenn Sie Ihren AnsiString verwenden möchten, können Sie auch eine Erweiterungsmethode erstellen .ToAnsiString()
:
public static AnsiString( this string s ) { return new AnsiString(s); }
Query<User>("select * from Users where Name=@Name", new {Name = "name".ToAnsiString()});