2014-06-05 16 views
8

Tôi có ứng dụng ADO.NET độc lập kết nối với một số cơ sở dữ liệu và có thể trích xuất thông tin cần thiết để chạy. Tôi đã nhấn một snag với DB2 và cách nó xử lý các tham số có tên, đặc biệt khi tôi sử dụng lại một tham số có tên trong cùng một truy vấn. Tôi biết một vài cách để giải quyết vấn đề này bằng cách thêm nhiều tham số hơn, nhưng về mặt lý thuyết nó sẽ hoạt động như trên các cơ sở dữ liệu khác mà tôi kết nối với tên tham số giống nhau.C# ADO.NET IBM DB2 đặt tên tham số có cùng tên ném Không đủ thông số được chỉ định Ngoại lệ

Những gì tôi đang làm là một chút phức tạp hơn và liên quan đến truy vấn con vv, nhưng để chứng minh, đi truy vấn sau đây:

chọn giá trị từ test.table nơi cola = @ key1 và colb = @ key1;

Tham số được đặt tên @ key1 được sử dụng hai lần.

Mã của tôi là như sau:

 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 [email protected] and [email protected]"; 
        dbConnection.Open(); 

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

      } // end dbConnection 
     } // end try 

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

Khi tôi chạy này tôi nhận được một ngoại lệ mà nói với tôi:

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

tôi nhận được những gì nó đang nói với tôi, nhưng tôi đang tìm giúp đỡ trong việc tìm ra cách tôi có thể có nhà cung cấp sử dụng tham số được đặt tên cho cả hai tham số vì chúng giống nhau. Dường như nó đang làm một số mù của các tham số được đặt tên và không nhận ra rằng chúng là các tham số có cùng tên. SQL Server dường như cho phép tôi làm điều này với cùng một mã ở trên. Tôi đoán nó chỉ là một trong những khác biệt trong các nhà cung cấp, nhưng hy vọng ai đó đã chạy vào điều này và có một giải pháp cho DB2 không đi vào mã DB2 cụ thể.

Cảm ơn, đánh giá cao sự trợ giúp.

+0

Bạn đã bao giờ tìm ra giải pháp cho vấn đề này chưa? Chúng tôi đang trải qua cùng một hành vi – Andronicus

+0

Thật không may, tôi đã không tìm thấy một giải pháp. Tôi đã phải tạo một tham số có tên khác và chỉ định nó cùng một giá trị. – Brent

+1

Thú vị. Khá mới với ADO.NET, tôi chưa nhận ra rằng một nhà cung cấp .NET có thể cho phép bạn sử dụng các tham số có tên với DB2 cho i. DB2 trên IBM i sử dụng '?' [Dấu tham số] (http://www-01.ibm.com/support/knowledgecenter/ssw_ibm_i_71/db2/rbafzpreph2.htm). Tôi giả sử một số lớp ở phía Windows dịch các tham số được đặt tên vào một dấu hỏi, trước khi gửi yêu cầu đến máy chủ. – WarrenT

Trả lời

0

Tôi cũng đã đào sâu hơn một chút và tôi tự hỏi liệu đó có phải là trình kết nối bạn đang sử dụng hay không. Vì vậy, tôi làm như sau (trong đó rất giống với những gì bạn đang làm)

trong tập tin ứng dụng cấu hình của tôi, tôi có

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

trong lớp Databasemanager tôi, tôi sẽ khởi tạo nó như vậy

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

Tôi thêm các thông số khác một chút. Tôi có một số Dictionary<string,object> mà tôi cũng thêm khi thiết lập truy vấn của mình. Để sử dụng ví dụ của bạn tôi sẽ có này

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

sau đó đọc là nơi mà các OP và tôi có mã tương tự

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

chạy cho biết đang làm việc cho tôi, vì vậy tôi tự hỏi, nếu sự khác biệt là ở nhà cung cấp mà chúng tôi đang sử dụng. Tôi đang sử dụng các thông số có tên trong sản xuất và đã ít nhất một năm nay, có thể gần 2 năm.

Tôi sẽ nói rằng tôi đã gặp phải lỗi tương tự khi về cơ bản chạy cùng mã hai lần, như thể hiện trong mã này

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

trên dòng 3 var list = array.ToList() là sửa chữa cho vấn đề mà bạn đang nhìn thấy đối với tôi .trước khi tôi có if (!array.Any()) mà sẽ chạy truy vấn và sử dụng các tham số (mà tôi xóa trước khi tôi execture truy vấn) sau đó khi tôi đi để liệt kê thông qua và in từng mục trong mảng tôi sau đó nhận được lỗi. Đối với tôi, vấn đề là nó đã chạy lại truy vấn mà tôi không còn tham số nữa. Sửa chữa là liệt kê truy vấn với ToList() và sau đó kiểm tra và in của tôi trên danh sách.

Các vấn đề liên quan