Jak programować? [zamknięte]

Pracowałem z małą rutyną, która jest używana do tworzenia połączenia z bazą danych:

Przed

public DbConnection GetConnection(String connectionName)
{
   ConnectionStringSettings cs= ConfigurationManager.ConnectionStrings[connectionName];
   DbProviderFactory factory = DbProviderFactories.GetFactory(cs.ProviderName);
   DbConnection conn = factory.CreateConnection();
   conn.ConnectionString = cs.ConnectionString;
   conn.Open();

   return conn;
}

Potem zacząłem przeglądać dokumentację. NET framework, aby zobaczyć, jakie są udokumentowane zachowania różnych rzeczy i sprawdzić, czy mogę sobie z nimi poradzić.

Na przykład:

ConfigurationManager.ConnectionStrings...

Dokumentacja mówi, że wywołanie ConnectionStrings rzuca ConfigurationErrorException jeśli nie może odzyskać kolekcja. W tym przypadku nie mogę nic zrobić, aby poradzić sobie z tym wyjątkiem, więc odpuszczę.


Następna część to rzeczywiste indeksowanie ConnectionStrings aby znaleźć connectionName :

...ConnectionStrings[connectionName];

W tym przypadku dokumentacja ConnectionStrings mówi, że właściwość zwróci null jeśli nazwa połączenia nie została znaleziona. mogę sprawdzić, czy to się dzieje, i rzucić wyjątek, aby pozwolić komuś wysoko, że dał Nieprawidłowa nazwa połączenia:

ConnectionStringSettings cs= 
      ConfigurationManager.ConnectionStrings[connectionName];
if (cs == null)
   throw new ArgumentException("Could not find connection string \""+connectionName+"\"");

Powtarzam to samo ćwiczenie z:

DbProviderFactory factory = 
      DbProviderFactories.GetFactory(cs.ProviderName);

Metoda GetFactory nie posiada dokumentacji co się stanie, jeśli nie można znaleźć fabryki podanej ProviderName. Nie jest udokumentowany powrót null, ale nadal mogę być defensywny, i sprawdź dla null:

DbProviderFactory factory = 
      DbProviderFactories.GetFactory(cs.ProviderName);
if (factory == null) 
   throw new Exception("Could not obtain factory for provider \""+cs.ProviderName+"\"");

Następna jest budowa obiektu DbConnection:

DbConnection conn = factory.CreateConnection()

Znowudokumentacja nie mówi co dzieje się, jeśli nie można utworzyć połączenia, ale ponownie mogę sprawdzić, czy obiekt zwraca NULL:

DbConnection conn = factory.CreateConnection()
if (conn == null) 
   throw new Exception.Create("Connection factory did not return a connection object");

Następnie ustawiamy właściwość obiektu Connection:

conn.ConnectionString = cs.ConnectionString;

Dokumenty nie mówią, co się stanie, jeśli nie można ustawić łańcucha połączenia. Czy to daje wyjątek? Ignoruje to? Jak w przypadku większości WYJĄTKÓW, jeśli wystąpił błąd podczas próby ustawienia ConnectionString połączenia, nic nie mogę zrobić, aby z niego odzyskać. Więc zrobię to. nic.


I wreszcie otwarcie połączenia z bazą danych:

conn.Open();

Metoda OtwartaDbConnection jest abstrakcyjna, więc to od dostawcy zstępującego z DbConnection zależy, jakie wyjątki wyrzucą. Nie ma również wskazówek w dokumentacji abstrakcyjnych metod otwartych na temat tego, czego mogę się spodziewać, jeśli wystąpi błąd. Jeśli był błąd połączenia, wiem, że nie mogę sobie z tym poradzić - będę musiał pozwolić, aby bańka się, gdzie rozmówca może pokazać niektóre UI do użytkownika, i niech spróbować ponownie.


Po

public DbConnection GetConnection(String connectionName)
{
   //Get the connection string info from web.config
   ConnectionStringSettings cs= ConfigurationManager.ConnectionStrings[connectionName];

   //documented to return null if it couldn't be found
    if (cs == null)
       throw new ArgumentException("Could not find connection string \""+connectionName+"\"");

   //Get the factory for the given provider (e.g. "System.Data.SqlClient")
   DbProviderFactory factory = DbProviderFactories.GetFactory(cs.ProviderName);

   //Undefined behaviour if GetFactory couldn't find a provider.
   //Defensive test for null factory anyway
   if (factory == null)
      throw new Exception("Could not obtain factory for provider \""+cs.ProviderName+"\"");

   //Have the factory give us the right connection object
   DbConnection conn = factory.CreateConnection();

   //Undefined behaviour if CreateConnection failed
   //Defensive test for null connection anyway
   if (conn == null)
      throw new Exception("Could not obtain connection from factory");

   //Knowing the connection string, open the connection
   conn.ConnectionString = cs.ConnectionString;
   conn.Open()

   return conn;
}

Podsumowanie

Więc moja funkcja czterech linii, stała się 12 liniami i wymagała 5 minut wyszukiwania dokumentacji. W końcu złapałem jeden przypadek, w którym metoda może zwrócić null. Ale w praktyce wszystko, co zrobiłem, to konwertowanie wyjątku access violation (jeśli próbuję wywołać metody na referencji null) na InvalidArgumentException .

Wyłapuję również dwa możliwe przypadki, w których może być null return objects; ale znowu wymieniłem tylko jeden wyjątek na inny.

Z drugiej strony, to wyłapało dwa problemy i wyjaśniało, co się stało w wiadomości o wyjątkach, a nie złe rzeczy dziejące się na drodze (tj.]}

Ale czy warto? Czy to przesada? Czy to defensywne programowanie poszło nie tak?

Author: Noldorin, 2009-06-27

14 answers

Ręczne sprawdzanie konfiguracji i wyrzucenie wyjątku nie jest lepsze niż pozwolenie frameworkowi na wyrzucenie wyjątku, jeśli brakuje konfiguracji. Po prostu powielasz Sprawdzanie warunków wstępnych, które i tak dzieje się wewnątrz metod frameworku, a to sprawia, że kodujesz gadatliwie bez żadnych korzyści. (W rzeczywistości możesz usuwać Informacje, rzucając wszystko jako podstawową klasę WYJĄTKÓW. Wyjątki rzucane przez framework są zazwyczaj bardziej dokładnie.)

Edit: ta odpowiedź wydaje się być nieco kontrowersyjna, więc trochę opracowania: Programowanie defensywne oznacza " przygotuj się na nieoczekiwane "(lub" bądź paranoikiem") i jednym ze sposobów, aby to zrobić, jest dokonanie wielu wstępnych kontroli. W wielu przypadkach jest to dobra praktyka, jednak tak jak w przypadku wszystkich praktyk, koszty powinny być porównywane z korzyściami.

Na przykład nie daje żadnej korzyści rzucenie wyjątku "nie można uzyskać połączenia z fabryki", ponieważ nie mówi wszystko o Dlaczego provider nie mógł zostać uzyskany - a następna linia i tak rzuci wyjątek, jeśli provider jest null. Tak więc koszt sprawdzenia warunku wstępnego (w czasie rozwoju i złożoności kodu) nie jest uzasadniony.

Z drugiej strony sprawdzenie, czy konfiguracja łańcucha połączenia jest obecna może być uzasadnione, ponieważ wyjątek może pomóc programistom w rozwiązaniu problemu. Wyjątek null otrzymasz w następnej linii anyway nie podaje nazwy ciągu połączenia, którego brakuje, więc kontrola warunków wstępnych zapewnia pewną wartość. Jeśli na przykład twój kod jest częścią komponentu, wartość jest dość duża, ponieważ użytkownik komponentu może nie wiedzieć, jakich konfiguracji wymaga komponent.

Inna interpretacja programowania defensywnego polega na tym, że nie należy tylko wykrywać błędów, należy również próbować odzyskać wszelkie błędy lub wyjątki, które mogą wystąpić. Nie wierzę. ogólnie to dobry pomysł.

Zasadniczo powinieneś obsługiwać tylko wyjątki, o których możesz zrobić. Wyjątki, z których i tak nie możesz odzyskać, powinny być po prostu przekazywane w górę do obsługi najwyższego poziomu. W aplikacji webowej obsługa najwyższego poziomu prawdopodobnie wyświetla ogólną stronę błędu. Ale w większości przypadków nie ma wiele do zrobienia, jeśli baza danych jest wyłączona lub brakuje kluczowej konfiguracji.

Niektóre przypadki, w których takie defensywne programowanie ma sens, jeśli akceptujesz wejście użytkownika, a to Wejście Może prowadzić do błędów. Jeśli na przykład użytkownik poda adres URL jako wejście, a aplikacja spróbuje pobrać coś z tego adresu URL, to bardzo ważne jest, aby sprawdzić, czy adres URL wygląda poprawnie i obsłużyć każdy wyjątek, który może wynikać z żądania. Dzięki temu możesz przekazać użytkownikowi cenne informacje zwrotne.

 31
Author: JacquesB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-02 12:02:55

Cóż, to zależy, kto jest twoją publicznością.

Jeśli piszesz kod biblioteczny, którego spodziewasz się użyć przez wiele innych osób, które nie będą z tobą rozmawiać o tym, jak go używać, to nie jest to przesada. Docenią twój wysiłek.

(to powiedziawszy, jeśli to robisz, sugeruję zdefiniowanie lepszych WYJĄTKÓW niż tylko System.Wyjątek, aby ułatwić osobom, które chcą złapać niektóre z Twoich wyjątków, ale nie inne.)

Ale jeśli masz zamiar go użyć siebie (lub ciebie i twojego kumpla), to oczywiście przesada i pewnie w końcu cię boli, czyniąc Twój kod mniej czytelnym.

 13
Author: mquander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-27 17:30:45

Chciałbym, żeby mój zespół tak kodował. Większość ludzi nawet nie rozumie sensu programowania defensywnego. Najlepsze, co robią, to zawinąć całą metodę w instrukcję try catch i pozwolić, aby wszystkie wyjątki były obsługiwane przez ogólny blok WYJĄTKÓW!

Czapki z głów Ian. Rozumiem twój dylemat. Sam przez to przeszedłem. Ale to, co zrobiłeś, prawdopodobnie pomogło jakiemuś deweloperowi kilka godzin uderzania klawiatury.

Pamiętaj, gdy używasz API. NET framework, czego się po nim spodziewasz? Co wydaje się naturalne? Zrób to samo ze swoim kodem.

Wiem, że to wymaga czasu. Ale wtedy jakość ma swoją cenę.

PS: naprawdę nie musisz obsługiwać wszystkich błędów i rzucać niestandardowego wyjątku. Pamiętaj, że twoja metoda będzie używana tylko przez innych programistów. Powinny one być w stanie samodzielnie ustalić wspólne wyjątki ramowe. To nie jest warte zachodu.

 7
Author: bobbyalex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-20 08:46:05

Twój przykład "przed" ma rozróżnienie: jest jasny i zwięzły.

Jeśli coś jest nie tak, wyjątek zostanie w końcu wyrzucony przez framework. Jeśli nie możesz nic zrobić z wyjątkiem, równie dobrze możesz pozwolić mu propagować stos wywołań.

Są jednak chwile, kiedy wyjątek jest wrzucany głęboko w ramy, które naprawdę nie rzuca światła na to, jaki jest rzeczywisty problem. Jeśli problem polega na tym, że nie masz poprawnego ciągu połączenia, ale framework rzuca wyjątek w stylu "invalid use of null", wtedy czasami lepiej jest złapać wyjątek i przerobić go z wiadomością, która jest bardziej znacząca.

Często sprawdzam obiekty null, ponieważ potrzebuję rzeczywistego obiektu do działania, a jeśli obiekt jest pusty, rzucony wyjątek będzie skośny. Ale sprawdzam obiekty null tylko wtedy, gdy Wiem, że to się stanie. Niektóre fabryki obiektów nie zwracają obiektów null; rzucają wyjątek zamiast tego sprawdzanie null będzie bezużyteczne w takich przypadkach.

 6
Author: Robert Harvey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-27 17:33:47

Myślę, że nie napiszę żadnej z tych null-reference sprawdzania logiki-przynajmniej, nie sposób, w jaki to zrobiłeś.

Moje programy pobierające ustawienia konfiguracyjne z pliku konfiguracyjnego aplikacji sprawdzają wszystkie te ustawienia przy starcie. Zwykle buduję statyczną klasę, która zawiera ustawienia i odwołuje się do właściwości tej klasy (a nie ConfigurationManager) gdzie indziej w aplikacji. Są ku temu dwa powody.

Po pierwsze, jeśli aplikacja nie jest poprawnie skonfigurowana, to nie idzie do pracy. Wolałbym to wiedzieć w momencie, gdy program odczytuje plik konfiguracyjny, niż w pewnym momencie w przyszłości, gdy próbuję utworzyć połączenie z bazą danych.

Po Drugie, sprawdzenie poprawności konfiguracji nie powinno być problemem obiektów, które opierają się na konfiguracji. Nie ma sensu zmuszać się do wstawiania czeków w całym kodzie, jeśli już wykonałeś te czeki z góry. (Są od tego wyjątki, oczywiście-dla przykład, długotrwałe aplikacje, w których musisz być w stanie zmienić konfigurację podczas działania programu i mieć te zmiany odzwierciedlone w zachowaniu programu; w programach takich jak ten musisz przejść do ConfigurationManager, gdy potrzebujesz ustawienia.)

Ja też nie sprawdzałbym null-reference przy wywołaniach GetFactory i CreateConnection. Jak napisałbyś przypadek testowy, aby wykonać ten kod? Nie możesz, bo nie wiesz jak sprawić, by te metody zwracały null - nawet nie wiedz, że jest możliwe aby te metody zwróciły null. Więc zastąpiłeś jeden problem-twój program może rzucić NullReferenceException w Warunkach, których nie rozumiesz-innym, bardziej znaczącym: w tych samych tajemniczych warunkach, Twój program uruchomi kod, którego nie przetestowałeś.

 3
Author: Robert Rossney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-28 19:52:50

Moja zasada kciuków to:

Don ' t catch if the message of the rzucony wyjątek ma znaczenie dla dzwoniący.

Tak więc, NullReferenceException nie ma odpowiedniej wiadomości, sprawdziłbym czy jest null i wrzucił wyjątek z lepszą wiadomością. ConfigurationErrorException ma znaczenie, więc go nie łapię.

Jedynym wyjątkiem jest sytuacja, gdy "kontrakt" GetConnection nie pobiera łańcucha połączeń w konfiguracji plik.

Jeśli jest tak, że GetConnection powinno mieć kontrakt z niestandardowym wyjątkiem, który mówi, że nie można odzyskać połączenia, możesz zawinąć ConfigurationErrorException w niestandardowym wyjątku.

Innym rozwiązaniem jest określenie, że GetConnection nie może rzucać (ale może zwracać null), a następnie dodajesz "ExceptionHandler" do swojej klasy.

 1
Author: Nicolas Dorier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-28 20:45:08

Brakuje dokumentacji metody. ;-)

Każda metoda ma określone parametry wejściowe i wyjściowe oraz określone zachowanie wynikowe. W Twoim przypadku coś w stylu: "zwraca poprawne otwarte połączenie w przypadku powodzenia, else zwraca null(lub rzuca XXXException, jak chcesz). Pamiętając o tym zachowaniu, możesz teraz zdecydować, jak defensywnie powinieneś programować.

  • Jeśli twoja metoda powinna ujawnić szczegółowe informacje, dlaczego i co się nie powiodło, zrób to tak, jak zrobiłeś i sprawdź i złap wszystko i wszystko i zwróć odpowiednie informacje.

  • Ale, jeśli jesteś po prostu zainteresowany otwartą DBConnection lub po prostu null (lub jakiś wyjątek zdefiniowany przez użytkownika) w przypadku błędu, po prostu zawiń wszystko w try/catch i zwróć null (lub jakiś wyjątek) w przypadku błędu, a obiekt else.

Więc powiedziałbym, że zależy to od zachowania metody i oczekiwanego wyniku.

 1
Author: MicSim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-20 09:01:57

Ogólnie rzecz biorąc, wyjątki specyficzne dla bazy danych powinny być przechwytywane i ponownie wyrzucane jako coś bardziej ogólnego, jak (hipotetyczny) wyjątek DataAccessFailure. Kod wyższego poziomu w większości przypadków nie musi wiedzieć, że czytasz dane z bazy danych.

Innym powodem do szybkiego przechwytywania tych błędów jest to, że często zawierają one pewne szczegóły bazy danych w swoich wiadomościach, takie jak "No such table: ACCOUNTS_BLOCKED" lub "user key invalid: 234234". Jeśli to propaguje się do użytkownika końcowego, to jest złe w kilku sposoby:

  1. mylące.
  2. Potencjalne naruszenie bezpieczeństwa.
  3. żenujące dla wizerunku Twojej firmy (wyobraź sobie, że klient czyta komunikat o błędzie z prymitywną gramatyką).
 1
Author: quant_dev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-20 09:27:09

Zakodowałbym to dokładnie tak, jak przy pierwszej próbie.

Jednak użytkownik tej funkcji chroniłby obiekt połączenia za pomocą bloku USING.

Naprawdę nie lubię tłumaczyć WYJĄTKÓW, jak robią to twoje inne wersje, ponieważ bardzo trudno jest dowiedzieć się, dlaczego się zepsuł (baza danych w dół? Nie masz uprawnień do odczytu pliku konfiguracyjnego itp?).

 0
Author: Joshua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-28 20:11:27

Zmieniona wersja nie dodaje wiele wartości, o ile aplikacja ma funkcję obsługi AppDomain.UnexpectedException, która zrzuca łańcuch exception.InnerException i wszystkie ślady stosu do jakiegoś pliku dziennika (lub nawet lepiej, przechwytuje minidump), a następnie wywołuje Environment.FailFast.

Na podstawie tych informacji, w miarę łatwo będzie określić, co poszło nie tak, bez konieczności komplikowania kodu metody z dodatkowym sprawdzaniem błędów.

Zauważ, że lepiej jest obsługiwać AppDomain.UnexpectedException I wywoływać Environment.FailFast zamiast posiadanie najwyższego poziomu try/catch (Exception x), ponieważ w przypadku tego ostatniego, pierwotna przyczyna problemu prawdopodobnie zostanie przysłonięta przez dalsze wyjątki.

Dzieje się tak dlatego, że jeśli złapiesz wyjątek, wszystkie otwarte bloki finally zostaną uruchomione i prawdopodobnie wyrzucą więcej WYJĄTKÓW, co ukryje oryginalny wyjątek (lub co gorsza, usunie pliki w celu przywrócenia jakiegoś stanu, być może niewłaściwych plików, może nawet ważnych plików). Nigdy nie należy przechwytywać wyjątku wskazującego na nieprawidłową stan programu, z którym nie wiesz, jak sobie radzić - nawet w bloku najwyższego poziomu main funkcji try/catch. Obsługa AppDomain.UnexpectedException i wywołanie Environment.FailFast jest innym (i bardziej pożądanym) czajnikiem ryb, ponieważ zatrzymuje finally bloki przed uruchomieniem, a jeśli próbujesz zatrzymać swój program i zapisać przydatne informacje bez robienia dalszych szkód, zdecydowanie nie chcesz uruchamiać swoich {6]} bloków.

 0
Author: Daniel Earwicker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-28 20:51:46

Nie zapomnij sprawdzić OutOfMemoryExceptions... wiesz, to może się zdarzyć.

 0
Author: dr. evil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-28 20:51:57

Zmiany Iaina wyglądają dla mnie sensownie.

Jeśli używam systemu i używam go niewłaściwie, chcę jak najwięcej informacji o niewłaściwym użyciu. Np. jeśli zapomnę wstawić jakieś wartości do konfiguracji przed wywołaniem metody, chcę mieć InvalidOperationException z Komunikatem opisującym mój błąd, a nie Keynotfoundexception / NullReferenceException.

It ' s all about context IMO. Widziałem kilka dość nieprzeniknionych wiadomości WYJĄTKÓW w moim czasie, ale innym razem domyślne wyjątek pochodzący z frameworka jest w porządku.

Ogólnie rzecz biorąc, myślę, że lepiej jest błądzić po stronie ostrożności, zwłaszcza gdy piszesz coś, co jest mocno używane przez innych ludzi lub zazwyczaj głęboko w wykresie wywołania, gdzie błąd jest trudniejszy do zdiagnozowania.

Zawsze staram się pamiętać, że jako twórca kodu lub systemu jestem w lepszej sytuacji do diagnozowania błędów niż ktoś, kto właśnie z niego korzysta. Czasami zdarza się, że kilka linijek sprawdzanie kodu + niestandardowa wiadomość wyjątku może skumulować wiele godzin czasu debugowania (a także ułatwić sobie życie, ponieważ nie zostaniesz pociągnięty do cudzej maszyny, aby debugować swój problem).

 0
Author: Mark Simpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-28 20:52:35

W moich oczach twoja próbka " po " nie jest tak naprawdę defensywna. Ponieważ defensywne byłoby sprawdzenie części pod twoją kontrolą, które byłyby argumentem connectionName (sprawdź czy nie ma null lub empty i wyrzuć ArgumentNullException).

 0
Author: Lucero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-28 20:52:52

Dlaczego nie podzielić metody, którą masz po dodaniu całego programowania defensywnego? Masz kilka odrębnych bloków logicznych, które wymagają osobnych metod. Dlaczego? Ponieważ wtedy hermetyzujesz logikę, która należy do siebie, a wynikowa metoda Publiczna po prostu łączy te bloki we właściwy sposób.

Coś takiego (edytowane w edytorze SO, więc bez sprawdzania składni / kompilatora. Może się nie skompilować; -))

private string GetConnectionString(String connectionName)
{

   //Get the connection string info from web.config
   ConnectionStringSettings cs= ConfigurationManager.ConnectionStrings[connectionName];

   //documented to return null if it couldn't be found
   if (cs == null)
       throw new ArgumentException("Could not find connection string \""+connectionName+"\"");
   return cs;
}

private DbProviderFactory GetFactory(String ProviderName)
{
   //Get the factory for the given provider (e.g. "System.Data.SqlClient")
   DbProviderFactory factory = DbProviderFactories.GetFactory(ProviderName);

   //Undefined behaviour if GetFactory couldn't find a provider.
   //Defensive test for null factory anyway
   if (factory == null)
      throw new Exception("Could not obtain factory for provider \""+ProviderName+"\"");
   return factory;
}

public DbConnection GetConnection(String connectionName)
{
   //Get the connection string info from web.config
   ConnectionStringSettings cs = GetConnectionString(connectionName);

   //Get the factory for the given provider (e.g. "System.Data.SqlClient")
   DbProviderFactory factory = GetFactory(cs.ProviderName);


   //Have the factory give us the right connection object
   DbConnection conn = factory.CreateConnection();

   //Undefined behaviour if CreateConnection failed
   //Defensive test for null connection anyway
   if (conn == null)
      throw new Exception("Could not obtain connection from factory");

   //Knowing the connection string, open the connection
   conn.ConnectionString = cs.ConnectionString;
   conn.Open()

   return conn;
}

PS: To nie jest kompletny refaktor, tylko dwa pierwsze bloki.

 0
Author: Erik van Brakel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-02 12:17:24