Oracle.DataAccess kullanarak yaptığım sorgularda ora:1722 ("invalid number") hatası alıyorum (OracleGlobalization)

 

Problem:

Oracle üzerinde yazılmış bir prosedürü Asp.Net üzerinden çalıştırmak istiyorum.

Bunun için aşağıdaki gibi bir kod kullanıyordum.

using Oracle.DataAccess.Client;
.....

    using (var conn = new OracleConnection()) {
                    string query = "PROSEDURUM";
                    conn.ConnectionString = connString;
                    var comm = new OracleCommand(query, conn);
                    comm.CommandType = CommandType.StoredProcedure;
                    comm.Parameters.Add("p_1", OracleDbType.Varchar2).Value = p_1degeri;
                    comm.Parameters.Add("p_2", OracleDbType.Int32).Value = p_2degeri;
        comm.Parameters.Add("cur", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
                    conn.Open();
                    var adapter = new OracleDataAdapter(comm);
                    adapter.Fill(dtTable);

Ancak kodu çalıştırdığımda sürekli ORA:1722 hatası alıyorum. p_2degeri için girdiğim değer 1 olsa bile aynı hatayı almaya devam ediyorum.

Olası nedenler:

1. Oracle Command’ın default ayarlarında BindByName = false olarak ayarlıdır. Bu ayarı elle değiştirmezseniz parametreleri ismine göre değil de sizin verdiğiniz sıraya göre alır. Yani Prosedürdeki parametre sırasıyla sizin command’e eklediğiniz parametrelerin sırası aynı değilse parametreleri yanlış eşleştirir.

Çözüm: Bunu önlemek için command’ınızın BindByName propertysini true olarak set etmeniz gerekiyor.

comm.BindByName = true;

2. Session Globalization ile Db Globalization birbirinden farklı olabilir. Bu durumda sayı ondalıklı olmasa bile oracle hatalı sayı uyarısı verir. Böyle bir durumun olup ılmadığını kontrol etmek için aşağıdaki sql sözcüğünü çalıştırmak gerekiyor.

SELECT
  a1.parameter as "Parameter",
  a1.value as "Database value",
  a2.value as "Instance value",
  a3.value as "Session value"
FROM
  nls_database_parameters a1
  LEFT JOIN nls_instance_parameters a2 ON a1.parameter = a2.parameter
  LEFT JOIN nls_session_parameters a3 ON a1.parameter = a3.parameter
ORDER BY
  a1.parameter asc;

Sorgu sonucunda db ve session formatlarını görebilirsiniz.

Çözüm: Bu durumu çözmek için connectionunuzu açtıktan sonra şağıdaki kodu çalıştırmanız gerekiyor. (Benin durumumda serverdaki numaricCharacters “.,” benim sessionumdaki ise “,.” görünüyordu)

OracleGlobalization SessionGlob = conn.GetSessionInfo();
SessionGlob.NumericCharacters = ".,";
conn.SetSessionInfo(SessionGlob);

Ben örnekteki kodu sadece sayı için yazdım Tarih hatası alıyorsanız onu da aşağıdaki gibi bir kodla düzeltebilirsiniz

 SessionGlob.DateFormat = "YYYY/MM/DD";
Not: Kurulum yaparken bu nls ayarlarını yapmadığımız için bu şekilde uğraşıyoruz. Baştan sunucuya göre konfigürasyonu yaparsak böyle bir problemle karşılaşmayız.