Gdzie umieścić wspólne połączenie z bazą danych dla moich klas

11

Mam kilka klas (repozytoriów), które wykonują zadanie zapisywania / pobierania niektórych obiektów w / z bazy danych; wszystkie muszą ustanowić połączenie z jedną bazą danych.

Pomyślałem, aby uniknąć przedefiniowania ConnectionStringi SqlConnectionw każdej klasie, przekazując im otwarte połączenie. Więc gdzie / kiedy jest najlepsze miejsce / czas, aby zdefiniować / otworzyć to połączenie i przekazać je klasom?

Czy istnieją lepsze podejścia / wzorce mające dostęp do tego wspólnego zasobu?

Ahmad
źródło

Odpowiedzi:

10

Przekazywanie otwartego połączenia każdej klasie prawdopodobnie nie jest najlepszym pomysłem. Zapoznaj się z tematem Tworzenie połączeń z bazą danych - Zrób to raz lub dla każdego zapytania?

Zaleca otwieranie i zamykanie połączenia dla każdego zapytania, które chcesz uruchomić, zamiast przekazywania otwartego połączenia do repozytorium.

Możesz spróbować czegoś takiego, aby pomóc w zarządzaniu połączeniami.

public class Repository
{
    private readonly string _connectionString;

    public Repository()
    {
        _connectionString = ConfigurationManager.ConnectionStrings["connString"].ConnectionString
    }

    protected SqlConnection GetConnection()
    {
         return new SqlConnection(_connectionString);
    }


}

public sealed class UserRespository : Repository
{

    public User GetUsers()
    {
        using (var connection = GetConnection())
        {
            using (var commnad = new SqlCommand("SqlQuery", connection))
            {
                //Execute Query
                //Return results
            }
        }
    }
}
Gibson
źródło
5

Posiadanie otwartego połączenia i przekazywanie go między klasami to na ogół zły pomysł. Jasne, otwarcie połączenia jest dość dużym spadkiem wydajności, ale pula połączeń już załatwiła to przez ponowne użycie już otwartych połączeń. Uwaga: zawsze czekaj tak długo, jak to możliwe, aby zadzwonić connection.Open(), szczególnie w kodzie wielowątkowym, ponieważ spowoduje to przypisanie połączenia do twojej metody (co potencjalnie zwiększy potrzebną liczbę otwartych połączeń z bazą danych).

Aby uczynić twoje klasy tak ogólnymi, jak to możliwe, zaleciłbym, aby klasa podstawowa ujawniła metodę z IDbConnection, a twoje repozytoria będą miały bardziej ogólną implementację.

internal abstract class Repository
{
    private static readonly string ConnectionString = ConfigurationManager.ConnectionStrings["myconnectionstring"].ConnectionString;

    protected IDbConnection GetConnection()
    {
        return new SqlConnection(ConnectionString);
    }
}

public class MyRepository : Repository
{
    public IEnumerable<object> Get()
    {
        using (var connection = GetConnection())
        {
            connection.Open();

            ...
        }
    } 
}
Richard Jansson
źródło