2011-04-15 24 views
6

używam System.Data.OracleClient który ma parametr wiążące po imieniu i sprawdzasz CommandText i parametry są zsynchronizowane:ORA-01008 ze wszystkimi zmiennymi związany

public string CommandText { get; set; } 
    public IEnumerable<OracleParameter> Parameters { get; set; } 

    private void VerifyThatAllParametersAreBound() 
    { 
     var variableNames = Regex.Matches(CommandText, ":\\w+") 
      .Cast<Match>().Select(m => m.Value).ToArray(); 
     var parameteterNames = Parameters.Select(p => p.ParameterName).ToArray(); 

     var unboundVariables = variableNames.Except(parameteterNames).ToArray(); 
     if (unboundVariables.Length > 0) 
     { 
      throw new Exception("Variable in CommandText missing parameter: " 
       + string.Join(", ", unboundVariables) + "."); 
     } 

     var unboundParameters = parameteterNames.Except(variableNames).ToArray(); 
     if (unboundParameters.Length > 0) 
     { 
      throw new Exception("Parameter that is not used in CommandText: " 
       + string.Join(", ", unboundParameters) + "."); 
     } 
    } 

Jeszcze jedno zapytanie rzuca ORA-01008: not all variables bound. Przy ręcznym wstawianiu wartości parametrów do naruszającego tekst CommandText uruchamiane jest zapytanie, więc wartości CommandText i parametry powinny być w porządku. Używam: jako przedrostka zarówno dla zmiennych, jak i nazw parametrów i działa dla innych zapytań.

Jak ustalić przyczynę tego wyjątku?

+1

czy masz kod składający zapytania? Czy próbowałeś też z klientami .net (lub innymi sprzedawcami)? Myślę, że Microsoft nie dostarcza już klientowi Oracle. –

+0

Niejasno pamiętam problem z jednym z klientów Oracle, że parametry musiały być powiązane dokładnie w tej samej kolejności, w jakiej pojawiły się w zapytaniu lub nie działały - czy to może być problem tutaj? – Rup

+0

@Nick - Polecenie było aktualizacją z ~ 40 parametrami, więc dla czytelności i ip-powodów upuściłem je. Próbowałem z ODT.NET z Oracle, ale miał problem z wdrożeniem go. (Zobacz także komentarz poniżej). – Grastveit

Odpowiedz

7

Błąd nie określał wartości DBNull.Value dla wartości null. Więc

new OracleParameter(":Foo", item.Foo) 

musiał zawczasu z

item.Foo == null 
    ? new OracleParameter(":Foo", DBNull.Value) 
    : new OracleParameter(":Foo", item.Foo) 

myślę, że pracował wcześniej z ODT.NET bez null kontroli, ale nie potwierdził. Najwyraźniej System.Data.OracleClient upuszcza parametry z wartością null.

0

Wierzę, że Microsoft ma deprecated OracleClient w ramach ADO.NET około 2 lata temu.

Możesz rozważyć użycie komponentów dostępu do danych Oracle (ODAC odp.net). Łatwe tworzenie (i sprawdzanie liczników) parametrów przy użyciu klasy OracleParameter. Skonfiguruj i zainstaluj dokumenty znalezione here. Och, możesz dostać się do ich struktury Entity (i LINQ) również (wciąż beta myślę?).

Coś do poważnego rozważenia.

+0

Tak, wolałbym używać tego, co polecają zarówno oracle, jak i microsoft, ale musiałem wprowadzić moje próby [wstrzymane] (http://stackoverflow.com/questions/5581752/program-defensively-against-odac-instantclient). Z pięciocyfrowymi kodami błędów jestem trochę rozczarowany ogólnymi wiadomościami. ;) – Grastveit

3

Jeśli zdasz zerowej jako wartość parametru, można dostać „Nie wszystkie zmienne związane” Jeśli zdasz DBNull.Value masz błąd wykonania gdzieś w OracleClient. Aby przekazać wartość NULL, należy użyć ciągu .Empty, OracleClient zamienia go na NULL dla dowolnego typu bazy danych.