No najgorsza opcja to opcja 4. Połączenie z bazą danych powinno mieć krótki okres życia. JEDNAK jeśli chodzi o aplikacje desktopowe i jeśli używasz zaawansowanego ORMa (EF, nHibernate), to wtedy jest zalecenie, żeby połączenie było otwarte przez cały okres życia formy. Raczej chodzi tutaj o okienka dialogowe. Wtedy ORMy działają fajnie, bo ogarniają automatycznie update tylko zmienionych pól. Teraz można by się pokusić - czy forma główna też tak powinna pracować? Moim zdaniem nie. Bo ona życie przez całą aplikację, a nie przez chwilę. Więc połączenie jest otwarte przez całą aplikację.
Jeśli chodzi o DI, to przynajmniej Microsoft jest jeszcze bardziej radykalny i twierdzi, że połączenie z bazą danych powinno istnieć tylko dla konkretnej klasy. Mówiąc o radykalności, mam na myśli tutaj web. Microsoft radzi, żeby połączenie z bazą danych nie było otwierane dla całego requestu, tylko dla konkretnych serwisów - oddzielnie. Pewnie nie w każdej sytuacji to się sprawdzi, ale tak powinno być.
Kończąc - trzymaj otwarte połączenie tak krótko, jak się da. Generalnie @somekind dał idealne wskazówki. Wszystkie zapytania w ramach jednej operacji biznesowej powinny używać jednego połączenia. To znaczy (pseudokody):
var connection = OpenConnection();
connection.BeginTransaction();
foreach(var item in list)
{
UpdateOrInsert(item);
}
connection.CommitTransaction();
connection.Close();
albo:
void RegisterClient(Client client)
{
var connection = OpenConnection();
bool result = ClientExists(connection, client);
if(!result)
{
connection.BeginTransaction();
InsertSomeClientData(connection, client);
InsertOtherClientData(connection, client);
UpdateSomeShit(connection);
connection.CommitTransaction();
}
connection.Close();
}
(do purystów - celowo pominąłem ewentualny RollbackTransaction, żeby nie zaciemniać obrazu :))