Question sur l'héritage - Récupération de données à partir d'un fichier de base de données Access et de SQL Express

StackOverflow https://stackoverflow.com/questions/256027

Question

Je développe une application qui sera connectée à la base de données Access au début et il est prévu de passer à MS SQL ou à SQL Express dans un avenir proche. Les structures de tables de données sont les mêmes pour les deux types de bases de données et j'essaie d'éviter de dupliquer le code et d'essayer de trouver le moyen de minimiser le code.

Par exemple, j'ai écrit la fonction suivante pour récupérer des données de la base de données Access:

public static DataTable GetActiveCalls()
    {
        string select = "SELECT call_id, call_time, msisdn, status FROM call WHERE status = 0 OR status = 1 ORDER by call_id ASC";
        OleDbCommand cmd = new OleDbCommand(select, conn);
        DataTable dt = new DataTable("Active Calls");
        OleDbDataAdapter DA = new OleDbDataAdapter(cmd);
        try
        {
            conn.Open();
            DA.Fill(dt);
        }
        catch (Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
        return dt;
    }

et le code suivant concerne la base de données SQL Express:

public static DataTable GetActiveCalls()
    {
        string select = "SELECT call_id, call_time, msisdn, status FROM call WHERE status = 0 OR status = 1 ORDER by call_id ASC";
        SqlCommand cmd = new SqlCommand(select, conn);
        DataTable dt = new DataTable("Active Calls");
        SqlDataAdapter DA = new SqlDataAdapter(cmd);
        try
        {
            conn.Open();
            DA.Fill(dt);
        }
        catch (Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
        return dt;
    }

Ces deux méthodes sont presque les mêmes. Les seules différences sont SqlCommand / OleDbCommand et SqlDataAdapter / OleDbDataAdapter. Certaines méthodes prennent des arguments, par exemple:

public static void AddMessage(string callID, string content)
    {
        string select =
            "INSERT INTO message(key, direction, content, read, write_time) VALUES (@callId, 0, @content, 0, @insertTime)";
        OleDbCommand cmd = new OleDbCommand(select, conn);
        cmd.Parameters.AddWithValue("callId", callID.ToString());
        cmd.Parameters.AddWithValue("content", content);
        cmd.Parameters.AddWithValue("insertTime", DateTime.Now.ToString());
        try
        {
            conn.Open();
            cmd.ExecuteScalar();
        }
        catch (Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
    }

Dans ce cas, la chaîne de requête SQL est également identique pour les deux bases de données, mais il existe une différence entre le type de cmd (SqlCommand / OleDbCommand).

J'apprécierais vraiment si quelqu'un pouvait donner une suggestion sur la manière d'éviter de dupliquer le code et d'optimiser le problème donné.

Était-ce utile?

La solution

Vous pouvez utiliser les interfaces IDbDataAdapter et IDbCommand, indépendantes de la base de données, puis créer les instances concrètes à l'aide d'une fabrique. Ici est un exemple.

Toutefois, je vous conseillerais d'utiliser une solution ORM telle que NHibernate si votre application n'est pas très simple, car Il existe de petites différences dans le langage SQL entre Access et SQL Server qui peuvent rendre votre code d’accès aux données plus complexe.

Autres conseils

Vous devriez consulter les bits d'accès aux données de la bibliothèque d'entreprise . Les détails du fournisseur de base de données sous-jacent sont résumés pour vous. Par exemple:

string sql = @"UPDATE tblContent 
                        SET Title = @Title, Content = @Content, IsPublic = @IsPublic, ItemOrder = @ItemOrder
                        WHERE ContentItemID = @ContentItemID";

Database db = DatabaseFactory.CreateDatabase();
using(DbCommand cmd = db.GetSqlStringCommand(sql))
{
    db.AddInParameter(cmd, "Title", DbType.String, title);
    db.AddInParameter(cmd, "Content", DbType.String, content);
    db.AddInParameter(cmd, "IsPublic", DbType.Boolean, isPublic);
    db.AddInParameter(cmd, "ItemOrder", DbType.Int32, itemOrder);
    db.AddInParameter(cmd, "ContentItemID", DbType.Int32 , contentItemID);

    db.ExecuteNonQuery(cmd);
}

... ou ...

string sql = "SELECT MenuText FROM tblMenuItems WHERE MenuItemID = @MenuItemID";

Database db = DatabaseFactory.CreateDatabase();
using(DbCommand cmd = db.GetSqlStringCommand(sql))
{
    db.AddInParameter(cmd, "MenuItemID", DbType.Int32, menuItemID);

    using(IDataReader dr = db.ExecuteReader(cmd))
    {
        while(dr.Read())
        {
            return dr["MenuText"].ToString();
        }
        return null;
    }
}

Les deux exemples ci-dessus fonctionnent avec Access et MS SQL. Si vous vous en tenez aux instructions SQL compatibles avec Jet et MS SQL, vous ne devriez pas rencontrer de problèmes.

Lorsque vous passez d'Access à MS SQL, modifiez simplement la chaîne de connexion, par exemple, à partir de:

<connectionStrings>
    <add 
         name="ContentManager" 
         connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Content.mdb;" 
         providerName="System.Data.OleDb"/>
</connectionStrings>

... à ...

<connectionStrings>
    <add
        name="ContentManager"
        connectionString="Data Source=your.sql.server;Initial Catalog=content;Persist Security Info=True;User ID=cmuser;Password=password"
        providerName="System.Data.SqlClient" />
</connectionStrings>

Pour cela, il vous suffit de référencer les DLL suivantes dans la distribution EL:

Microsoft.Practices.EnterpriseLibrary.Common.dll
Microsoft.Practices.EnterpriseLibrary.Data.dll

Vaut le détour.

À la vôtre
Kev

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top