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
-
05-07-2019 - |
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é.
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