Requete SQL avec jointure vers Objet
Bonjour,
je recherche la meilleur pratique pour gérer les résultats des jointures SQL dans des objets. Actuellement, je travaille de la façon suivante :
Pour chaque table :
Je crée une classe chargée de mapper les champs de la table à des propriétés.
Je crée une classe service contenant les requetes SQL.
Pour illustrer simplement :
Ma BDD a deux tables : Marchandise et TypeMarchandise. Je crée donc 4 classes :
Classes de la table Marchandise :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
public class Marchandise
{
public string Code { get; set; }
public short Quantite { get; set; }
public decimal Poids { get; set; }
/// <summary>
/// Constructeur lors d'un select
/// </summary>
/// <param name="r"></param>
public Marchandise(IDataReader r)
{
Code = (r["CodeMarch"] as string)?.Trim() ?? "0";
Quantite = (short)r["QttMarch"];
this.Poids = (decimal)r["PoidsMarc"];
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
public class MarchandiseService
{
public Marchandise Get(string code, IDbConnection db)
{
var cmd = db.CreateCommand();
Marchandise result = null;
cmd.CommandText = $"SELECT * FROM MARCHANDISE WHERE CODE = {code}";
using (IDataReader r = cmd.ExecuteReader())
{
if (r.Read())
result = new Marchandise(r);
}
return result;
}
} |
Classes de la table TypeMarchandise :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public class TypeMarchandise
{
public string Code { get; set; }
public string Libelle { get; set; }
public TypeMarchandise(IDataReader r)
{
Code = (r["CodeMarch"] as string)?.Trim() ?? "0";
Libelle = (r["LibelleMarch"] as string)?.Trim() ?? "Non renseigné";
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public TypeMarchandise Get(string code, IDbConnection db)
{
var cmd = db.CreateCommand();
TypeMarchandise result = null;
cmd.CommandText = $"SELECT * FROM TYPEMARCHANDISE WHERE CODE = '{code}'";
using (IDataReader r = cmd.ExecuteReader())
{
if (r.Read())
result = new TypeMarchandise(r);
}
return result;
}
} |
Actuellement, si j'ai besoin pour mon traitement d'avoir un objet avec les propriétés de la classe Marchandise et le libellé de cette dernière, je fais :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
public void test()
{
IDbConnection db = new SqlConnection();
using (db)
{
db.Open();
string codeMarch = "toto";
//Instanciation des classes services
MarchandiseService srvMarch = new MarchandiseService();
TypeMarchandiseService srvTypeMarch = new TypeMarchandiseService();
//Récupère les data en BDD
Marchandise march = srvMarch.Get(codeMarch, db);
TypeMarchandise typeMarch = srvTypeMarch.Get(codeMarch, db);
MarchandiseAvecLibelle marchEtLib = new MarchandiseAvecLibelle
{
Code = march.Code,
Poids = march.Poids,
Quantite = march.Quantite,
Libelle = typeMarch.Libelle
};
}
} |
Dans ce cas, je suis obligé de faire 2 requêtes SQL pour avoir mon objet final.
Pour optimiser cela, il serait bien plus simple de faire une jointure effectuant la requête :
"SELECT * FROM MARCHANDISE as a INNER JOIN TYPEMARCHANDISE as b ON a.CODE = b.CODE"
Cependant, si je garde ma logique de 1 table = 1 classe objet et 1 classe service, je ne vois pas comment gérer efficacement les jointures.
Dans cet exemple, il est simple de créer un objet spécialement pour la jointure telle que l'objet MarchandiseEtLibelle.
Mais dans le cadre de mon développement, les jointures peuvent être multiples et elles peuvent concerner des dizaines de champs.
J'avais pour but de ne pas avoir de requête dans mon traitement autre que les requêtes effectuées par mes classes "Service" mais, à moins de faire autant de classes objet / service que de jointure, je ne vois pas comment faire ...
Quelle serait la meilleur pratique pour gérer cela ?
Merci d'avance pour vos conseils.