10

我得到一个字符串作为输出参数,并且需要知道在调用 AddOutParameter 时为 Size 参数设置什么。

我知道我可以使用一些巨大的数字,比如 int.MaxValue,但想知道最佳实践。

在 SQL Server 中,列实际上是唯一标识符类型。正在执行的 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 背景)。

我应该找出 uniqueidentifier 列的最大大小并将大小设置为该大小吗?如果我对 VARCHAR 或 NVARCHAR 列做同样的事情呢?

我希望框架能为我做这件事;我不想为我得到的每个字符串指定一个大小作为输出。有人对最佳实践有任何建议吗?

我已经阅读了下面的帖子以及 MSDN 文档,但是我还没有找到真正的最佳实践答案。

AddOutParameter - 查找 DBType.Int32 长度的非幻数方法

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

4

1 回答 1

17

我们发现您对 UniqueIdentifer 使用了错误的类型。您应该使用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

正如预期的那样,派生的大小与所有字符类型的长度字段匹配,除了最大值和预期长度的返回值。然而,在查看最大类型和 DbTypes 时,我们对前三个有一些新问题。

  • 那个 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
于 2012-06-01T21:57:43.073 回答