2011-10-21 15 views
7

Od pewnego czasu pakuję obiekty OracleConnection i OracleCommand w instrukcje USING, jednak po uruchomieniu analizatora kodu odkryłem, że OracleParameter również implementuje IDisposable. Czy poniższy kod jest prawidłowy? Czy istnieje lepsza technika czytelności lub struktury? Na pierwszy rzut oka wydaje się być zagraconym za pomocą instrukcji USING:C# IDisposable Using: Best Practice

using (OracleConnection conn = new OracleConnection(connectionstring)) 
{ 
    conn.Open(); 
    using (OracleCommand cmd = new OracleCommand(sql, conn)) 
    { 
     cmd.BindByName = true; 

     using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input)) 
     { 
      param1.Value = int.Parse(value1); 
      cmd.Parameters.Add(param1); 
     } 

     using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input)) 
     { 
      param2.Value = value2; 
      cmd.Parameters.Add(param2); 
     } 

     using (OracleDataReader dr = cmd.ExecuteReader()) 
     { 
      // loop data here... 
     } 
    } 
} 

Odpowiedz

7

Chcesz pozbyć parametrów dopiero na samym końcu ich wykorzystania, w tym podczas kwerendy (i ewentualnie odczyt wyników):

using (OracleConnection conn = new OracleConnection(connectionstring)) 
{ 
    conn.Open(); 
    using (OracleCommand cmd = new OracleCommand(sql, conn)) 
    { 
     cmd.BindByName = true; 

     using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input)) 
     using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input)) 
     { 
      param1.Value = int.Parse(value1); 
      cmd.Parameters.Add(param1); 
      param2.Value = value2; 
      cmd.Parameters.Add(param2); 

      using (OracleDataReader dr = cmd.ExecuteReader()) 
      { 
       // loop data here... 
      } 
     } 
    } 
} 

Zauważ że można umieścić wiele using oświadczenia w wiersz. To dlatego, że, podobnie jak w rachunku if,

  1. using oświadczenie jest uważane za proste stwierdzenie (nawet z blokiem); i
  2. Instrukcja A może mieć blok lub instrukcję poniżej.
+0

Chociaż było wiele podobnych odpowiedzi, doceniam, że dostarczyłeś zarówno przykłady, jak i komentarze. – Shawn

+0

Dzięki! Cieszę się, że mogę pomóc. :-) –

1

Nie jestem pewien, czy będzie działać poprawnie. Należy wziąć pod uwagę, że po zakończeniu użytkowania oba parametry powinny zostać usunięte. Fakt, że Twój obiekt cmd.Parameters nadal zawiera odniesienie do nich, nie wyklucza tego, co może się wydarzyć w metodzie Dispose w postaci OracleParameter. Dla wszystkich intensywnych celów deweloper tego obiektu może czyścić pola, które twój OracleCommand spodziewa się wypełnić.

Istnieje pewne niebezpieczeństwo. Jeśli jesteś absolutnie pewny, że chcesz prawidłowo zutylizować swój OracleParameters, sugeruję, abyś pozbył się ich po użyciu przy użyciu OracleDataReader.

Należy pamiętać, że generalnie wywołuje się Dispose po zakończeniu używania obiektu. Mówisz, żeby zwolnił wszystkie zasoby, które wstrzymuje z pulą. Jeśli nie używasz przedmiotu, nie wyrzucaj go przedwcześnie.

0

Nie jest to prawdą, ponieważ wyrzucasz parametry jeszcze przed ich użyciem.

Zamiast tego powinna więc to tak

OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input); 

param1.Value = int.Parse(value1); 
cmd.Parameters.Add(param1); 


OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input); 

param2.Value = value2; 
cmd.Parameters.Add(param2); 


using (OracleDataReader dr = cmd.ExecuteReader()) 
{ 
    // loop data here... 
} 

param1.dispose(); 
param2.dispose(); 
1
using (OracleConnection conn = new OracleConnection(connectionstring)) 
using (OracleCommand cmd = new OracleCommand(sql, conn)) 
using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, 
     System.Data.ParameterDirection.Input)) 
using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, 
     System.Data.ParameterDirection.Input)) 
} 
    conn.Open(); 
    cmd.BindByName = true; 

    param1.Value = int.Parse(value1); 
    cmd.Parameters.Add(param1); 

    param2.Value = value2; 
    cmd.Parameters.Add(param2); 

    using (OracleDataReader dr = cmd.ExecuteReader()) 
    { 
     // loop data here... 
    } 
} 
0

można spojrzeć na kod źródłowy połączenia i polecenia to wyrzucać parametry? jeśli obiekt połączenia lub polecenia udostępnia wzór, zawija parametry i usuwa je po ich usunięciu. powinieneś się tym martwić. które moim zdaniem powinno/powinno.

0

Ten kod jest niepoprawny. tworzone przez ciebie parametry są nadal używane poza zasięgiem instrukcji using, ponieważ dodajesz je do zbioru parametrów, ale instrukcja using wywoła Dispose dla parametrów po opuszczeniu kontrolki przez kontrolkę. Co oznacza, że ​​kiedy nadejdzie czas, aby użyć parametrów wewnątrz theyâ polecenia zostaną disoised z już

0

Według MSDN, trzeba tylko użyć using dla Connection i DataReader obiektów. Nigdy nie widziałem using (lub .Dispose()) używane z obiektami parametrów ADO.NET. Gdyby to było konieczne, a nawet pożądane, myślę, że pojawiłoby się to już jakiś czas w ciągu ostatnich 10 lat.

+2

MSDN mówi o obiektach dostarczonych przez BCL. Ich wdrożenie może bardzo dobrze wymagać Utylizacji parametrów. Dlaczego mieliby implementować IDisposable, gdyby nie były przeznaczone do usunięcia? –

+0

Albo oni bardzo dobrze nie mogą. Nigdy nie widziałem żadnego kodu ADO.NET (dla implementacji Oracle ani nikogo innego), który nazwałby Dispose() na obiekcie parametru lub umieścił go w bloku 'using'. Ponownie, gdyby wyrzucenie parametrów było konieczne, to już dawno temu podniosłoby to swoją głowę. – MusiGenesis

+2

Twoja rada jest taka, że ​​mimo, że obiekt implementuje IDisposble, nie wyrzucaj go, chyba że jest to problem? Brzmi jak zła rada dla mnie. –