【问题标题】:TableAdapter always returns null for scalar function in SQL Server 2008在 SQL Server 2008 中,TableAdapter 始终为标量函数返回 null
【发布时间】:2014-07-08 22:46:20
【问题描述】:

我遇到了一个奇怪的行为,我可以在一个简单的示例项目中缩小范围。

我正在尝试将相应的 Visual Studio 术语从德语翻译成英语

组件包括: - Visual Studio 2013 速成版 - C# - MSSQL 服务器 2008 R2 - .NET 框架 4.5 - 使用数据集和查询

示例函数很简单:

 CREATE FUNCTION [dbo].[fTest]
    (   )
    RETURNS INT
    AS
    BEGIN
        RETURN 42
    END

然后,我使用“现有存储过程”通过 TableAdapter 配置助手包含了一个 DataSet 并包含了一个查询,并将其保留为默认设置。 Visual Studio 在上下文菜单上有一个“数据预览”功能。在那里我会收到正确的结果值。

现在添加一些简单的代码:

    using functionTest.DataSet1TableAdapters;
    using System;

    namespace functionTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                QueriesTableAdapter qta = new QueriesTableAdapter();
                object result = qta.fTest();
                int? resI = (int?)result;
                Console.WriteLine("result: " + resI);
            }
        }
    }

奇怪的是结果总是为空。

编辑:

生成的 TableAdapter 代码:

namespace functionTest.DataSet1TableAdapters {


    /// <summary>
    ///Represents the connection and commands used to retrieve and save data.
    ///</summary>
    [global::System.ComponentModel.DesignerCategoryAttribute("code")]
    [global::System.ComponentModel.ToolboxItem(true)]
    [global::System.ComponentModel.DataObjectAttribute(true)]
    [global::System.ComponentModel.DesignerAttribute("Microsoft.VSDesigner.DataSource.Design.TableAdapterDesigner, Microsoft.VSDesigner" +
        ", Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
    [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")]
    public partial class QueriesTableAdapter : global::System.ComponentModel.Component {

        private global::System.Data.IDbCommand[] _commandCollection;

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")]
        protected global::System.Data.IDbCommand[] CommandCollection {
            get {
                if ((this._commandCollection == null)) {
                    this.InitCommandCollection();
                }
                return this._commandCollection;
            }
        }

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")]
        private void InitCommandCollection() {
            this._commandCollection = new global::System.Data.IDbCommand[1];
            this._commandCollection[0] = new global::System.Data.SqlClient.SqlCommand();
            ((global::System.Data.SqlClient.SqlCommand)(this._commandCollection[0])).Connection = new global::System.Data.SqlClient.SqlConnection(global::functionTest.Properties.Settings.Default.connectionString);
            ((global::System.Data.SqlClient.SqlCommand)(this._commandCollection[0])).CommandText = "dbo.fTest";
            ((global::System.Data.SqlClient.SqlCommand)(this._commandCollection[0])).CommandType = global::System.Data.CommandType.StoredProcedure;
            ((global::System.Data.SqlClient.SqlCommand)(this._commandCollection[0])).Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@RETURN_VALUE", global::System.Data.SqlDbType.Int, 4, global::System.Data.ParameterDirection.ReturnValue, 10, 0, null, global::System.Data.DataRowVersion.Current, false, null, "", "", ""));
        }

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")]
        [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")]
        public virtual object fTest() {
            global::System.Data.SqlClient.SqlCommand command = ((global::System.Data.SqlClient.SqlCommand)(this.CommandCollection[0]));
            global::System.Data.ConnectionState previousConnectionState = command.Connection.State;
            if (((command.Connection.State & global::System.Data.ConnectionState.Open) 
                        != global::System.Data.ConnectionState.Open)) {
                command.Connection.Open();
            }
            object returnValue;
            try {
                returnValue = command.ExecuteScalar();
            }
            finally {
                if ((previousConnectionState == global::System.Data.ConnectionState.Closed)) {
                    command.Connection.Close();
                }
            }
            if (((returnValue == null) 
                        || (returnValue.GetType() == typeof(global::System.DBNull)))) {
                return null;
            }
            else {
                return ((object)(returnValue));
            }
        }
    }
}

编辑: 另一个提示:内部 CommandCollection 包含有效结果。我在调试器中验证了这一点,并通过公开 CommandCollection 并访问它:

IDataParameterCollection test = qta._commandCollection[0].Parameters;
SqlParameter param = (SqlParameter) test[0];
int? res = (int?) param.Value;

【问题讨论】:

  • 你能分享 QueriesTableAdapter 的来源吗?
  • 当 C# 和 SQL server 的数据类型不匹配时会出现这种情况。但是我们可以在提供 QueriesTableAdapter 的源代码后提供具体原因。
  • 试试这个,int? resI = (int?)result.ToString();
  • 感谢您编辑标题。 “int?resI =(int?)result.ToString();”导致编译器报错“cannot convert from type string to int?”

标签: c# .net sql-server-2008 visual-studio-2013 tableadapter


【解决方案1】:

看来,使用 command.executescalar() 从标量值函数返回的对象始终为 null。

因此无法通过这种方式检索返回值。我认为这是 MS 的问题,因为这当然是显而易见的做法。

解决方法是将上面生成的代码编辑如下:

替换

returnValue = command.ExecuteScalar();

与

command.ExecuteScalar();
returnValue = command.Parameters["@RETURN_VALUE"].Value;

当然,“@RETURN_VALUE”必须与您的 tableadapter 中分配的名称相匹配。

这对我有用...希望它有所帮助。

如果你编辑生成的代码

【讨论】:

    猜你喜欢
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 2021-08-15
    • 2019-05-05
    • 1970-01-01
    • 2019-03-16
    • 1970-01-01
    相关资源
    最近更新 更多