草庐IT

C# ADO.NET IBM DB2 命名参数具有相同的名称抛出没有足够的参数指定异常

coder 2024-06-03 原文

我有一个相当不可知的 ADO.NET 应用程序,它连接到许多数据库并且能够提取必要的信息来运行。我遇到了 DB2 及其处理命名参数的问题,尤其是当我在同一个查询中重用命名参数时。我知道有几种方法可以通过简单地添加更多参数来解决这个问题,但理论上它应该像在我连接的其他数据库上一样工作,因为参数名称相同。

我正在做的事情有点复杂,涉及子查询等,但为了演示,采用以下查询:

从 test.table 中选择值,其中 cola=@key1 和 colb=@key1;

命名参数@key1被使用了两次。

我的代码如下:

       try
        {
            DbProviderFactory dbfFactory = DbProviderFactories.GetFactory("IBM.Data.DB2.iSeries");
            using (DbConnection dbConnection = dbfFactory.CreateConnection())
            {
                dbConnection.ConnectionString = "DataSource=xxx.xxx.xxx.xxx;UserID=xxxxxxxx;password=xxxxxxxxx";

                using (DbCommand dbCommand = dbConnection.CreateCommand())
                {
                    IDbDataParameter iddpParameter1 = dbCommand.CreateParameter();
                    iddpParameter1.ParameterName = "@key1";
                    iddpParameter1.DbType = DbType.String;
                    iddpParameter1.Value = "1";

                    dbCommand.Parameters.Add(iddpParameter1);
                    dbCommand.CommandType = CommandType.Text;
                    dbCommand.CommandText = "select value from test.table where cola=@key1 and colb=@key1";
                    dbConnection.Open();

                    using (IDataReader idrReader = dbCommand.ExecuteReader())
                    {
                        while (idrReader.Read())
                        {
                                   ...
                        }
                    }
                }

            } // end dbConnection
        } // end try

        catch (Exception ex)
        {
            Console.Write(ex.Message);
        }

当我运行它时,我得到一个异常告诉我:

System.InvalidOperationException: Not enough parameters specified.  The command requires 2 parameter(s), but only 1 parameter(s) exist in the parameter collection.

我明白它告诉我的内容,但我正在寻求帮助,以弄清楚如何让提供者对两个参数使用命名参数,因为它们是相同的。似乎它正在对命名参数进行盲目计数,而没有意识到它们是相同的命名参数。 SQL Server 似乎允许我使用上面的相同代码来执行此操作。我猜这只是提供程序中的差异之一,但希望有人遇到过这个问题并有一个不涉及特定 DB2 代码的 DB2 解决方案。

谢谢,感谢您的帮助。

最佳答案

好吧,我做了更多的挖掘,我想知道它是否可能是您正在使用的连接器。所以我正在做以下事情(这与你正在做的事情非常相似)

在我的应用配置文件中有

<connectionStrings>
    <add name="AWOLNATION" providerName="Ibm.Data.DB2" connectionString="Server=sail:50000;Database=Remix;" />
</connectionStrings>

在我的 Databasemanager 类中,我会像这样初始化它

    public static DatabaseManager Instance(string connectionStringName)
    {
        var connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
        if (connectionStringSettings == null) throw new MissingMemberException("[app.config]", string.Format("ConnectionStrings[{0}]", connectionStringName));
        return new DatabaseManager(connectionStringSettings);
    }

    private DatabaseManager(ConnectionStringSettings connectionInformation)
    {
        _connectionInformation = connectionInformation;
        _parameters = new Dictionary<string, object>();
    }
    private void Initialize()
    {
        _connection = DbProviderFactories.GetFactory(_connectionInformation.ProviderName).CreateConnection();
        _connection.ConnectionString = _connectionInformation.ConnectionString;

        _command = _connection.CreateCommand();
    }

不过我添加的参数有点不同。我有一个 Dictionary<string,object>我在设置查询时也添加了。要使用你的例子,我会有这个

    public IEnumerable<object> GetSomething(string key)
    {
        var sql = "select value from test.table where cola = @key1 and colb = @key1";
        _manager.AddParameter("@key1", key);

        return _manager.ExecuteReader<object>(sql, ToSomethignUseful);
    }

    private object ToSomethignUseful(DatabaseManager arg)
    {
        return new { Value = arg.GetArgument<object>("value") };
    }

然后阅读是 OP 和我有相似代码的地方

    public IEnumerable<T> ExecuteReader<T>(string sql, Func<DatabaseManager, T> conversionBlock)
    {
        Initialize();
        using (_connection)
        {
            _connection.Open();
            _command.CommandText = sql;
            _command.CommandType = CommandType.Text;

            if (_parameters.Count > 0)
                AddParameters(_command, _parameters);

            _parameters.Clear();

            using (_reader = _command.ExecuteReader())
            {
                while (_reader.Read())
                {
                    yield return conversionBlock(this);
                }
            }
        }
    }
    private static void AddParameters(DbCommand command, Dictionary<string, object> parameters)
    {
        foreach (var param in parameters)
        {
            command.Parameters.Add(CreateParameter(command, param.Key, param.Value));
        }
    }

    private static DbParameter CreateParameter(DbCommand command, string key, object value)
    {
        var parameter = command.CreateParameter();
        parameter.ParameterName = key;
        parameter.Value = value;

        return parameter;
    }

运行上述代码对我有用,所以我想知道区别是否在于我们使用的提供程序。我在生产中使用命名参数,现在至少使用了一年,可能接近 2 年。

我要说的是,我确实在两次运行相同的代码时遇到了同样的错误,如这段代码所示

    public static void IndendedPrintForEach<T>(this IEnumerable<T> array, string header, Func<T, string> consoleStringConverterMethod)
    {
        var list = array.ToList();
        var color = Console.ForegroundColor;
        Console.ForegroundColor = ConsoleColor.Magenta;
        Console.WriteLine($"<<<{header}>>>");
        Console.ForegroundColor = color;

        if (!list.Any())
        {
            Console.ForegroundColor = ConsoleColor.DarkRed;
            Console.WriteLine("    ************NoItemsFound************");
            Console.ForegroundColor = color;
        }
        else
        {
            foreach (var item in list)
                Console.WriteLine($"    {consoleStringConverterMethod(item)}");
        }
    }

第 3 行 var list = array.ToList()是您为我看到的问题的解决方案。在我有if (!array.Any())之前这将运行查询并使用参数(我在执行查询之前清除了这些参数)然后当我去枚举并打印数组中的每个项目时我得到了错误。对我来说,问题是它正在重新运行我没有更多参数的查询。解决方法是使用 ToList() 枚举查询,然后在列表上进行检查和打印。

关于C# ADO.NET IBM DB2 命名参数具有相同的名称抛出没有足够的参数指定异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24070890/

有关C# ADO.NET IBM DB2 命名参数具有相同的名称抛出没有足够的参数指定异常的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  2. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  3. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  4. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  5. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  6. ruby-on-rails - 在默认方法参数中使用 .reverse_merge 或 .merge - 2

    两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option

  7. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  8. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  9. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  10. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

随机推荐