0 Replies Latest reply: Mar 25, 2013 7:30 AM by 998959 RSS

    IndexOutOfRangeException in DataReader if Thread Culture changed.

    998959
      Hi,

      i think we found a bug in ODAC (4.112.3.0). If Thread.CurrentThread Culture is set to some Language which implements ToUpper in a different way, DataReader.GetOrdinal throws exception.
      Is this a known Problem? We will change it to send already uppercased names to GetOrdinal but it would be simpler for us if it is fixed in ODAC.

      Hier is a UnitTest which reproduces it:

      using System;
      using System.Data;
      using System.Data.Common;
      using System.Globalization;
      using System.Threading;
      using NHibernate.Exceptions;
      using NUnit.Framework;

      namespace LocalDbTests {
      [TestFixture, Explicit]
      public class TestOracleReaderCultureDependency {
      [Test]
      public void ReproduceBug() {
      string connectionString = CreateConnectionString("localhost", 1521, "xe", "test", "test");
      using (var conn = OpenConnection(connectionString)) {
      // table1 (col1 int, col2i, int)
      using (var cmd = conn.CreateCommand()) {
      cmd.CommandText = "select col1, col2i from table1";
      using (var reader = cmd.ExecuteReader()) {
      // In English is all well
      Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
      Assert.AreEqual(0, reader.GetOrdinal("col1"));
      Assert.AreEqual(1, reader.GetOrdinal("col2i"));

      // And now in Turkish
      Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("tr");
      Assert.AreEqual(0, reader.GetOrdinal("col1"));
      // GetOrdinal throws exception
      Assert.Throws<IndexOutOfRangeException>(() => reader.GetOrdinal("col2i"));

      // col2i.ToUpper is not COL2I in Turkish
      Assert.AreNotEqual("COL2I", "col2i".ToUpper());
      // Should use ToUpper(CultureInfo.InvariantCulture)
      Assert.AreEqual("COL2I", "col2i".ToUpper(CultureInfo.InvariantCulture));
      }
      }
      }
      }

      public static string CreateConnectionString(string hostname, int port, string sid, string username, string password) {
      return string.Format("data source= (DESCRIPTION= (ADDRESS_LIST= (ADDRESS= (PROTOCOL= TCP)(HOST= {0})(PORT= {1})))(CONNECT_DATA= (SID= {2})(SERVER = DEDICATED))); User ID={3}; Password={4}; Self Tuning=false", hostname, port, sid, username, password);
      }

      private IDbConnection OpenConnection(string connectionString) {
      var factory = DbProviderFactories.GetFactory("Oracle.DataAccess.Client");
      var connection = factory.CreateConnection();
      if (connection == null)
      throw new ADOConnectionException("Error creating IDbConnection.", null);
      connection.ConnectionString = connectionString;
      connection.Open();
      return connection;
      }
      }
      }