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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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é"; } }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 : Sélectionner tout - Visualiser dans une fenêtre à part
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; } }
Dans ce cas, je suis obligé de faire 2 requêtes SQL pour avoir mon objet final.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 }; } }
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.
Partager