在返回字符串时,Database.AddOutParameter中的Size参数应该使用什么?

10
我将获得一个字符串作为输出参数,并需要知道在调用AddOutParameter时为Size参数设置什么。
我知道我可以使用一些巨大的数字,比如int.MaxValue,但想知道最佳实践。
在SQL Server中,该列实际上是uniqueidentifier类型。正在执行的T-SQL语句插入记录,然后将一些输出变量设置为新插入记录的ID和GUID。这是我正在使用的实际代码,但变量名称已更改。
database.AddOutParameter(cmd, "@someInt", DbType.Int32, 0);
database.AddOutParameter(cmd, "@someString", DbType.String, 0);

database.ExecuteNonQuery(cmd);

someInt = (int)database.GetParameterValue(cmd, "@someInt");
someString = database.GetParameterValue(cmd, "@someString").ToString();

执行时,我收到以下错误... System.InvalidOperationException: String[2]: Size 属性具有无效大小 0。
所以对我来说很明显,你不能仅使用字符串输出参数的大小为0。你可以在Int32输出参数中这样做,但我想字符串需要一个有效的大小。那么设置大小的最佳实践是什么?它可以只是一个巨大的大小,而不会影响性能吗?我可以将其设置为int.MaxValue或其他吗?是否有任何常量可以在此处使用;(没有看到任何String.MaxValue-您可能可以告诉我我是C#的新手,有Java背景)。
我应该找出唯一标识符列的最大大小,并将大小设置为该值吗?如果我正在为VARCHAR或NVARCHAR列做同样的事情呢?
我希望框架可以为我完成这项工作;我不想为我获得的每个字符串都指定一个大小。有人有什么建议吗?
我已经阅读了下面的帖子以及MSDN文档,但我还没有找到最佳实践的答案。

AddOutParameter - 以非魔法数字的方式查找 DBType.Int32 的长度

从 SQL Server 读取 VARBINARY(MAX) 到 C#


2
在SQL Server中,该列实际上是uniqueidentifier类型,为什么不直接使用DbType.Guid而不是DbType.String呢? - Conrad Frix
好评论。我不知道有一个DbType.Guid。我正在寻找DbType.UniqueIdentifier或类似的东西,可能是因为我没有注意到Guid类型。我的眼睛可能老了。非常感谢!我尝试了一下,使用DbType.Guid时可以将大小设置为0,而且没有运行时异常。不过,如果我从VARCHAR或NVARCHAR列中获取数据,最佳实践是如何设置大小呢? - Jim
使用Varchar和NVarchar时,我通常会将其匹配到源列或变量的大小。当类型不匹配时就很麻烦了。例如,如果没有DbType.Guid,我认为在Access 95中读取SQL Server Guids时会遇到问题。 - Conrad Frix
大小参数不应该是以字节为单位吗?所以,如果我有一个可能包含多字节字符的NVARCHAR(50)列,我不是必须将大小设置得比50高吗?您是否知道设置大小只比您需要的要高得多,例如int.MaxValue,是否会造成任何性能差异(或问题)? - Jim
1个回答

17

我们发现您在使用唯一标识符时使用了错误的类型。您应该使用 DbType.Guid 而不是字符串,但是您在评论中提出了其他问题,我不能在评论中回答并且我也不确定,所以我需要测试。

它们是

  • 对于不同的字符串输出参数,您应该设置什么大小?
  • 如果是Nvarchar或Varchar,这会有影响吗?
  • 如果太大或太小会发生什么?

我开始使用SqlCommandBuilder.DeriveParameters 来查找ADO.NET和SQL Server认为应该是什么,然后执行存储过程以查看我们的返回值。

Sql Type     | DbType                | Size | Returned string.Length()
----------------------------------------------------------------
Varchar(10)  | AnsiString            | 10   | 9
Char(10)     | AnsiStringFixedLength | 10   | 10
Nvarchar(10  | String                | 10   | 9
Varchar(max) | AnsiString            | -1   | 20,480 
NVarchar(max)| String                | -1   | 20,480

预期的派生大小与所有字符类型的长度字段匹配,除了最大值和返回值,其预期长度不匹配。但是,查看最大类型和 DbType 时,我们有一些新的问题需要解决,以配合我们的前三个问题。

  • AnsiString 类型怎么了?如果我们将其设置为 DbType.String,保持相同的大小,它是否会影响输出?答案:不会,可能是因为 .NET 字符串是 Unicode

  • 增加Paramater.Size会影响非最大值吗?答案:只有 char(10)。它通过添加空格来增加输出大小。

  • 减小Paramater.Size会影响非最大值吗?是的,它会截断返回值。

  • 大小为 -1 是什么魔法?答案:设置大小为 -1 将返回结果,就好像您已正确设置了它们一样

测试代码 .NET 4.0 SQL Server 2008

SQL 代码

CREATE PROCEDURE SomeOutput( 
@tenVC varchar(10)  output,
@tenC char(10) output,
@tenNVC nvarchar(10) output,
@maxVC varchar(max) output,
@maxNVC nvarchar(max) output,
@Indentifier uniqueidentifier output)
AS 


SELECT @tenC = '123456789',
       @tenVC = '123456789',
       @tenNVC = '123456789',
       @Indentifier = NEWID(),
       @maxVC = '',
       @maxNVC = ''



SELECT 
       @maxVC = @maxVC + '1234567890',
       @maxNVC = @maxNVC + '1234567890'
FROM
        master..spt_values 
WHERE
      type= 'P'    

C# 代码

static void Main(string[] args)
{

    using (SqlConnection cnn = new SqlConnection("Server=.;Database=Test;Trusted_Connection=True;"))
    {
        SqlCommand cmd = new SqlCommand("SomeOutput", cnn);
        cmd.CommandType = CommandType.StoredProcedure;
        cnn.Open();
        SqlCommandBuilder.DeriveParameters(cmd);

        Printparams(cmd.Parameters, "Derived");

        foreach (SqlParameter param in cmd.Parameters)
        {
            //By default output parameters are InputOutput
            //This will cause problems if the value is both null
            if (param.Direction == ParameterDirection.InputOutput )
                param.Direction = ParameterDirection.Output;

        }


        cmd.ExecuteNonQuery();

        Printparams(cmd.Parameters ,"Executed");


        cmd.Parameters["@tenVC"].DbType = DbType.String;
        cmd.Parameters["@tenNVC"].DbType = DbType.AnsiString;

        cmd.ExecuteNonQuery();

        Printparams(cmd.Parameters, "DbType change");



        foreach (SqlParameter param in cmd.Parameters)
        {
            if (param.DbType != DbType.Int32
                && param.DbType != DbType.Guid
                && param.Size != -1)
            {
                param.Size = param.Size * 2;

            }
        }

        cmd.ExecuteNonQuery();

        Printparams(cmd.Parameters, "Mangeled sizes up");


        foreach (SqlParameter param in cmd.Parameters)
        {
            if (param.DbType != DbType.Int32 
                && param.DbType != DbType.Guid
                && param.Size != -1)
            {
                param.Size = param.Size / 4;

            }
        }

        cmd.ExecuteNonQuery();

        Printparams(cmd.Parameters, "Mangeled sizes down");

        cmd.Parameters["@maxVC"].Size = Int32.MaxValue;
        cmd.Parameters["@maxNVC"].Size = Int32.MaxValue;

        cmd.ExecuteNonQuery();

        Printparams(cmd.Parameters, "Fixed max sizes");

        foreach (SqlParameter param in cmd.Parameters)
        {
            if (param.DbType != DbType.Int32
                && param.DbType != DbType.Guid)
            {
                param.Size = -1;

            }
        }

        cmd.ExecuteNonQuery();

        Printparams(cmd.Parameters, "is negative one magic");

        }
}

输出

Derived
@RETURN_VALUE : Int32 : 0 : ReturnValue : 0 :
@tenVC : AnsiString : 10 : InputOutput : 0 :
@tenC : AnsiStringFixedLength : 10 : InputOutput : 0 :
@tenNVC : String : 10 : InputOutput : 0 :
@maxVC : AnsiString : -1 : InputOutput : 0 :
@maxNVC : String : -1 : InputOutput : 0 :
@Indentifier : Guid : 0 : InputOutput : 0 :

Executed
@RETURN_VALUE : Int32 : 0 : ReturnValue : 1 : 0
@tenVC : AnsiString : 10 : Output : 9 : 123456789
@tenC : AnsiStringFixedLength : 10 : Output : 10 : 123456789
@tenNVC : String : 10 : Output : 9 : 123456789
@maxVC : AnsiString : -1 : Output : 20480 : 123456789012345678901234567
@maxNVC : String : -1 : Output : 20480 : 123456789012345678901234567
@Indentifier : Guid : 0 : Output : 36 : eccc3632-4d38-44e8-9edf-031

DbType change
@RETURN_VALUE : Int32 : 0 : ReturnValue : 1 : 0
@tenVC : String : 10 : Output : 9 : 123456789
@tenC : AnsiStringFixedLength : 10 : Output : 10 : 123456789
@tenNVC : AnsiString : 10 : Output : 9 : 123456789
@maxVC : AnsiString : -1 : Output : 20480 : 123456789012345678901234567
@maxNVC : String : -1 : Output : 20480 : 123456789012345678901234567
@Indentifier : Guid : 0 : Output : 36 : 94cb0039-8587-4357-88fb-25c

Mangeled sizes up
@RETURN_VALUE : Int32 : 0 : ReturnValue : 1 : 0
@tenVC : String : 20 : Output : 9 : 123456789
@tenC : AnsiStringFixedLength : 20 : Output : 20 : 123456789
@tenNVC : AnsiString : 20 : Output : 9 : 123456789
@maxVC : AnsiString : -1 : Output : 20480 : 123456789012345678901234567
@maxNVC : String : -1 : Output : 20480 : 123456789012345678901234567
@Indentifier : Guid : 0 : Output : 36 : 4de88f14-9963-4a78-b09b-bb6

Mangeled sizes down
@RETURN_VALUE : Int32 : 0 : ReturnValue : 1 : 0
@tenVC : String : 5 : Output : 5 : 12345
@tenC : AnsiStringFixedLength : 5 : Output : 5 : 12345
@tenNVC : AnsiString : 5 : Output : 5 : 12345
@maxVC : AnsiString : -1 : Output : 20480 : 123456789012345678901234567
@maxNVC : String : -1 : Output : 20480 : 123456789012345678901234567
@Indentifier : Guid : 0 : Output : 36 : 5e973e72-14e5-4b75-9cff-e88

Fixed max sizes
@RETURN_VALUE : Int32 : 0 : ReturnValue : 1 : 0
@tenVC : String : 5 : Output : 5 : 12345
@tenC : AnsiStringFixedLength : 5 : Output : 5 : 12345
@tenNVC : AnsiString : 5 : Output : 5 : 12345
@maxVC : AnsiString : 2147483647 : Output : 20480 : 123456789012345678901234567
@maxNVC : String : 2147483647 : Output : 20480 : 123456789012345678901234567
@Indentifier : Guid : 0 : Output : 36 : 6cab2b41-d4ba-42d2-a93a-e59

is negative one magic
@RETURN_VALUE : Int32 : 0 : ReturnValue : 1 : 0
@tenVC : String : -1 : Output : 9 : 123456789
@tenC : AnsiString : -1 : Output : 10 : 123456789
@tenNVC : AnsiString : -1 : Output : 9 : 123456789
@maxVC : AnsiString : -1 : Output : 20480 : 123456789012345678901234567
@maxNVC : String : -1 : Output : 20480 : 123456789012345678901234567
@Indentifier : Guid : 0 : Output : 36 : 0d69ed57-fab7-49c8-b03a-d75

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