在.Net框架中是否有一个内置的类可用于表示AnsiString?

4

对于Dapper,我需要构建支持传递AnsiString参数的功能。

数据库同时拥有Unicode和非Unicode字符串,选择正确的参数类型有时至关重要。

DbType.StringDbType.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的容器,并具有与上面示例类似的语义?


1
如果有人想知道为什么在过去的一天里提交问题需要超过一秒钟,这就是原因 :) - Sam Saffron
2个回答

1

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

因此,它支持:

  • ansi vs unicode
  • fixed vs dynamic length
  • 在动态长度的情况下,显式vs隐式(如果长度≤4000,则为4000;否则为“max”-这样可以保持查询计划的数量合理)

该类型在 dapper 中可用。


DbString是你自己的类吗? - Andrew Savinykh
@zespri - 是的,抱歉;我会让那更明确。Sam实际上是在“dapper”的背景下提问的,这也是DbString现在所在的地方。 - Marc Gravell
@ Marc Gravell:是的,谢谢,我理解了 Dapper 的上下文,只是在 Sam 的问题中他正在寻找一个现有的 BCL 类,所以我想澄清一下。现在这一切都很清楚,谢谢。 - Andrew Savinykh

0

我猜你可以使用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()});

1
我们研究了这个问题,但最终发现char[]并没有什么特别的 ANSI 特性,在大多数情况下这只是数据的重复。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接