Come dovrei incapsulare l'accesso al database?

7

Quali sono alcuni esempi di buone strutture di classe utilizzate per gestire l'accesso al database? Sono un fan dell'incapsulamento di classe e preferirei che i contenitori (ad es. Auto) non eseguano attività di database.

Mi piacerebbe anche la possibilità di abbandonare facilmente cose come una cache di database in futuro.

Spesso prendo lo schema delle classi contenitore, completo di getter e setter per la convalida e l'accesso al database eseguito da una singola classe singleton. Detto questo, questo spesso si confonde tra i due e diventa piuttosto confuso.

Scusa se la mia domanda è difficile da capire; Non sono assolutamente sicuro sui termini riguardanti i database. Non esitate a chiedere chiarimenti se necessario.

    
posta Will03uk 12.07.2012 - 00:09
fonte

3 risposte

9

Preferisco il schema del repository per incapsulare l'accesso ai dati. In poche parole, il repository è responsabile del caricamento di tutti i dati necessari per un oggetto specifico. Supponi di avere un oggetto Car, come nel tuo esempio. Ma tutti gli attributi per l'auto, marca, modello, anno, proprietari, caratteristiche (lettore CD, 4wd ecc.) Sono memorizzati in varie tabelle in tutto il database. Il repository determina come caricare e salvare i dati. Se sono necessarie più query più piccole, bene, ma solo il pattern del repository deve saperlo. Il livello di servizio che richiama il repository deve solo sapere quale repository richiamare.

Può quindi essere combinato con il schema di unità di lavoro . Quindi nel tuo esempio, il livello di servizio direbbe che è necessario caricare un'entità auto, ha una sorta di identificatore univoco e invia tale identificatore al repository. Il repository restituisce l'entità dell'automobile. Qualche altro codice manipola l'entità dell'automobile e rimanda tale entità al repository in modo che possa essere salvata.

Se vuoi davvero dare il massimo, il livello del repository esporrà solo interfacce, come ICarRepository. Il repository conterrebbe un fabbrica che il livello di servizio userebbe per ottenere l'interfaccia ICarRepository. Tutto l'accesso al database sarebbe nascosto dietro un'interfaccia, il che rende molto più facile il test delle unità.

    
risposta data 12.07.2012 - 04:07
fonte
6

Ho utilizzato il Pattern di strategia per incapsulare l'accesso ai dati. Questo modello ti consente di nascondere il tipo di memoria che stai utilizzando dietro un'interfaccia comune. Nell'interfaccia, definire i metodi di accesso ai dati ignorando il tipo di archiviazione (file, database, Web). Quindi, per la tua scelta di archiviazione corrente, in una classe che realizza l'interfaccia della strategia, implementa i dettagli di accesso ai dati. In questo modo la tua applicazione non si preoccupa dell'origine dati che stai utilizzando.

Puoi anche creare un livello di servizio che utilizza l'istanza della strategia di archiviazione dei dati corrente per definire più dettagli specifici dell'applicazione invece di combinare l'accesso ai dati e la logica aziendale insieme.

    
risposta data 12.07.2012 - 00:28
fonte
1

Questo è un esempio di modello di database factory;

using System.Reflection;
using System.Configuration;

public sealed class DatabaseFactory
{
    public static DatabaseFactorySectionHandler sectionHandler = (DatabaseFactorySectionHandler)ConfigurationManager.GetSection("DatabaseFactoryConfiguration");

    private DatabaseFactory() { }

    public static Database CreateDatabase()
    {
        // Verify a DatabaseFactoryConfiguration line exists in the web.config.
        if (sectionHandler.Name.Length == 0)
        {
            throw new Exception("Database name not defined in DatabaseFactoryConfiguration section of web.config.");
        }

        try
        {
            // Find the class
            Type database = Type.GetType(sectionHandler.Name);

            // Get it's constructor
            ConstructorInfo constructor = database.GetConstructor(new Type[] { });

            // Invoke it's constructor, which returns an instance.
            Database createdObject = (Database)constructor.Invoke(null);

            // Initialize the connection string property for the database.
            createdObject.connectionString = sectionHandler.ConnectionString;

            // Pass back the instance as a Database
            return createdObject;
        }
        catch (Exception excep)
        {
            throw new Exception("Error instantiating database " + sectionHandler.Name + ". " + excep.Message);
        }
    }
}
    
risposta data 12.07.2012 - 05:20
fonte

Leggi altre domande sui tag