Forum |  HardWare.fr | News | Articles | PC | Prix | S'identifier | S'inscrire | Aide | Shop Recherche
1399 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  objets métiers -> base de données

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

objets métiers -> base de données

n°1582733
j_v_e_t
Posté le 05-07-2007 à 10:27:23  profilanswer
 

Bonjour,
je souhaite faire un petit programme de gestion orienté objet avec utilisation d'une base de données pour sauvegarder les données. Je n'utilise pas d'outils de mapping objet/relationnel.
 
J'ai défini les objets métiers. Je souhaite savoir s'il doivent disposer eux-mêmes de méthodes pour l'insertion ou la séléction dans la base de données ou si je dois faire intervenir un élement extérieur.
Evidement les deux approches sont possibles mais je voudrais vos avis sur la pertinence des deux stratégies.
Merci.

mood
Publicité
Posté le 05-07-2007 à 10:27:23  profilanswer
 

n°1582755
cgo2
Dum spiro spero
Posté le 05-07-2007 à 11:30:33  profilanswer
 

Je vois pas bien quel "element extérieur" tu voudrais faire intervenir ?


---------------
When it's from Finland it's good.  - Mon blog
n°1582756
j_v_e_t
Posté le 05-07-2007 à 11:32:54  profilanswer
 

L'objet qui me permet de faire le lien entre l'interface graphique et les objets métiers par exemple.

n°1582977
MagicBuzz
Posté le 05-07-2007 à 19:29:19  profilanswer
 

Il existe effectivement plusieurs méthodes.
 
1/ tu te trimbales l'ensemble du code nécessaire aux accès dans la base de données dans tes objets métiers.
Avantages : Les objets métiers sont autonomes, et tu n'as pas à te soucier de la présence d'élément extérieur.
Inconvénients : Si la structure de la base de données change, ou si la méthode d'accès à cette dernière change, ou si tu veux mettre en place des solutions de cache évoluées, ou autres, tu vas être obligé de modifier énormément de code redondant, voir te heurter à des problèmes quasi insollubles
 
2/ Utiliser un objet d'accès à la base de données très basique (pour ainsi dire, une simple surcharge des méthodes des objets de Base du Framework), et les appeler depuis tes objets métiers.
Avantages : Moins de redondance que dans le premier cas, et maintenabilité accrue
Inconvénients : Les objets métiers font toujours des appels à des méthodes assez bas niveau, ce qui peut compromettre en partie l'évolutivité (si demain tu changes d'un système de SGBD pour une solution basée sur des fichiers plats, tes objets métier sont tout aussi impactés que dans le premier cas)
 
3/ Déporter complètement la couche "accès aux données" vers l'objet de base de données. Ainsi, l'objet de base de données contient non seulement la connection à la base, mais toutes les méthodes métiers permettant l'accès à la base.
Avantages : Abstraction totale de la couche des données. Ainsi la maintenance et l'évolutivité sont très aisées
Inconvénients : Déport de méthodes métier au sein d'un objet "générique". Ainsi, l'étude de l'objet métier seul est insuffisant pour connaître tous les tenants du fonctionnement de ce dernier.
 
4/ Incorporer les deux couches ensemble, grace à l'héritage. l'objet métier dispose des méthodes de base d'accès à la couche des données, tandis que l'objet métier en hérite afin de faire lui-même les traîtements dans la base, sans se soucier de la façon qu'il les fait
Avantages : à priori, tous les avantages des 3 solutions précédentes
Inconvéniets : à priori, aucun des inconvénients cités ci-dessus
 
Personnellement, j'utilise actuellement le système "3". Il est aisé à mettre en place, et facilement maintenable lorsque les objets métiers restent simples et peu nombreux.
 
Je viens d'imaginer le cas "4", qui me semble en tout points suppérieur. Mais vu que je viens de l'imaginer, je peux pas te garantir qu'il marche :D


Message édité par MagicBuzz le 05-07-2007 à 19:31:01
n°1583004
MagicBuzz
Posté le 05-07-2007 à 20:58:32  profilanswer
 

Je viens de tester en vitesse une implémentation pourrave du 4.
Spa trop pourri, faut juste pas avoir l'esprit tordu comme moi :D
 
La base de test

Code :
  1. CREATE TABLE produit (code varchar(16) PRIMARY KEY NOT NULL, nom varchar(50) NOT NULL)
  2. go
  3.  
  4. INSERT INTO produit (code, nom) VALUES ('P1', 'Produit 1');
  5. INSERT INTO produit (code, nom) VALUES ('P2', 'Produit 2');
  6. INSERT INTO produit (code, nom) VALUES ('P3', 'Nutella');


 
Le code C#

Code :
  1. using System;
  2.  
  3. namespace Couches
  4. {
  5.    class Program
  6.    {
  7.        static void Main(string[] args)
  8.        {
  9.            Console.WriteLine("Création de l'objet métier \"Produit\"." );
  10.            Produit p = new Produit();
  11.  
  12.            Console.WriteLine("Chargement des produits dont le nom commence par \"Produit\"." );
  13.            p.LoadProducts("Produit%" );
  14.            p.DisplayProducts();
  15.  
  16.            Console.WriteLine("Chargement du produit \"P1\" et renommage." );
  17.            p.LoadProduct("P1" );
  18.            p.UpdateProductName("Produit 1 renommé" );
  19.            p.DisplayProducts();
  20.  
  21.            Console.WriteLine("Chargement de tous les produits et tentative de mise à jour abusive." );
  22.            p.LoadProducts(string.Empty);
  23.            p.UpdateProductName("Test..." );
  24.            p.DisplayProducts();
  25.  
  26.            Console.WriteLine("Chargement de tous les produits dont le nom est \"Produit 2\"" );
  27.            Console.WriteLine("et mise à jour (si un seul produit)." );
  28.            p.LoadProducts("Produit 2" );
  29.            p.UpdateProductName("Test..." );
  30.            p.DisplayProducts();
  31.  
  32.            Console.ReadKey();
  33.        }
  34.    }
  35. }
  36.  
  37.  
  38. using System;
  39. using System.Data;
  40.  
  41. namespace Couches
  42. {
  43.    class Produit : DataBase
  44.    {
  45.        private DataTable dt;
  46.  
  47.        public Produit()
  48.        {
  49.            // Le constructeur de "DataBase" est implicitement appelé
  50.            
  51.            dt = new DataTable();
  52.        }
  53.  
  54.        public bool LoadProduct(string productcode)
  55.        {
  56.            if (Open())
  57.            {
  58.                object[,] filters = new object[1, 2];
  59.                filters[0,0] = "code";
  60.                filters[0,1] = productcode;
  61.                dt = LoadTable("produit", filters);
  62.                if (dt != null && dt.Rows.Count == 1)
  63.                    return true;
  64.            }
  65.            return false;
  66.        }
  67.  
  68.        public bool UpdateProductName(string productname)
  69.        {
  70.            if (Open() && dt != null && dt.Rows.Count == 1)
  71.            {
  72.                dt.Rows[0]["nom"] = productname;
  73.                if (SaveTable(dt) == 1)
  74.                    return true;
  75.            }
  76.            return false;
  77.        }
  78.  
  79.        public int LoadProducts(string namefilter)
  80.        {
  81.            if (!Open())
  82.            {
  83.                return -1;
  84.            }
  85.  
  86.            object[,] filters;
  87.  
  88.            if (namefilter.Length > 0)
  89.            {
  90.                filters = new object[1, 2];
  91.                filters[0, 0] = "nom";
  92.                filters[0, 1] = namefilter;
  93.                dt = LoadTable("produit", filters);
  94.            }
  95.            else
  96.            {
  97.                filters = new object[0, 0];
  98.            }
  99.  
  100.            dt = LoadTable("produit", filters);
  101.            if (dt != null)
  102.            {
  103.                return dt.Rows.Count;
  104.            }
  105.            else
  106.            {
  107.                return -1;
  108.            }
  109.        }
  110.  
  111.        public void DisplayProducts()
  112.        {
  113.            Console.WriteLine("--------------------------------------" );
  114.            if (dt != null)
  115.            {
  116.                for (int i = 0, cpt = dt.Rows.Count; i < cpt; i++)
  117.                {
  118.                    Console.WriteLine("Code : {0}", dt.Rows[i]["code"] as string);
  119.                    Console.WriteLine("Nom :  {0}", dt.Rows[i]["nom"] as string);
  120.                }
  121.            }
  122.            else
  123.            {
  124.                Console.WriteLine("Aucun produit chargé..." );
  125.            }
  126.            Console.WriteLine("--------------------------------------" );
  127.            Console.WriteLine();
  128.        }
  129.    }
  130. }
  131.  
  132.  
  133. using System;
  134. using System.Data;
  135. using System.Data.SqlClient;
  136. using System.Text;
  137.  
  138. namespace Couches
  139. {
  140.    class DataBase
  141.    {
  142.        private const string ConnectionString = "server=.;database=test;Integrated Security=SSPI";
  143.        private SqlConnection cnx;
  144.        private SqlDataAdapter da;
  145.  
  146.        protected DataBase()
  147.        {
  148.            cnx = new SqlConnection(ConnectionString);
  149.        }
  150.  
  151.        protected bool Open()
  152.        {
  153.            if ((cnx.State == ConnectionState.Open))
  154.            {
  155.                return true;
  156.            }
  157.  
  158.            try
  159.            {
  160.                cnx.Open();
  161.            }
  162.            catch
  163.            {
  164.                return false;
  165.            }
  166.  
  167.            if (cnx.State == ConnectionState.Open)
  168.            {
  169.                return true;
  170.            }
  171.            else
  172.            {
  173.                return false;
  174.            }
  175.  
  176.        }
  177.  
  178.        protected void Close()
  179.        {
  180.            try
  181.            {
  182.                cnx.Close();
  183.            }
  184.            catch { }
  185.        }
  186.  
  187.        protected DataTable LoadTable(string TableName, object[,] Filters)
  188.        {
  189.            if (!(cnx.State == ConnectionState.Open))
  190.            {
  191.                return null;
  192.            }
  193.  
  194.            StringBuilder sb = new StringBuilder(string.Format("select * from {0} where null is null", TableName));
  195.            SqlCommand cmd = cnx.CreateCommand();
  196.            cmd.CommandType = CommandType.Text;
  197.  
  198.            for (int i = 0, cpt = Filters.GetLength(0); i < cpt; i++)
  199.            {
  200.                if (Filters[i, 1].GetType().Name == "String" && (Filters[i, 1] as string).IndexOf('%') > -1)
  201.                {
  202.                    sb.Append(string.Format(" and {0} like @{0}", Filters[i, 0] as string));
  203.                }
  204.                else
  205.                {
  206.                    sb.Append(string.Format(" and {0} = @{0}", Filters[i, 0] as string));
  207.                }
  208.                SqlParameter p = cmd.CreateParameter();
  209.                p.Direction = ParameterDirection.Input;
  210.                p.ParameterName = Filters[i, 0] as string;
  211.                p.SqlValue = Filters[i, 1];
  212.                cmd.Parameters.Add(p);
  213.            }
  214.  
  215.            cmd.CommandText = sb.ToString();
  216.            da = new SqlDataAdapter(cmd);
  217.            SqlCommandBuilder cb = new SqlCommandBuilder(da);
  218.            da.InsertCommand = cb.GetInsertCommand();
  219.            da.UpdateCommand = cb.GetUpdateCommand();
  220.            da.DeleteCommand = cb.GetDeleteCommand();
  221.            DataTable dt = new DataTable();
  222.            da.Fill(dt);
  223.            return dt;
  224.        }
  225.  
  226.        protected int SaveTable(DataTable dt)
  227.        {
  228.            if (!(cnx.State == ConnectionState.Open))
  229.            {
  230.                return -1;
  231.            }
  232.  
  233.            DataTable Changes = dt.GetChanges();
  234.            int NbChanges = 0;
  235.  
  236.            if (dt != null && dt.Rows.Count > 0)
  237.            {
  238.                NbChanges = da.Update(Changes);
  239.                dt.AcceptChanges();
  240.            }
  241.  
  242.            return NbChanges;
  243.        }
  244.    }
  245. }


 
Sortie :


Création de l'objet métier "Produit".
Chargement des produits dont le nom commence par "Produit".
--------------------------------------
Code : P1
Nom :  Produit 1
Code : P2
Nom :  Produit 2
--------------------------------------
 
Chargement du produit "P1" et renommage.
--------------------------------------
Code : P1
Nom :  Produit 1 renommé
--------------------------------------
 
Chargement de tous les produits et tentative de mise à jour abusive.
--------------------------------------
Code : P1
Nom :  Produit 1 renommé
Code : P2
Nom :  Produit 2
Code : P3
Nom :  Nutella
--------------------------------------
 
Chargement de tous les produits dont le nom est "Produit 2"
et mise à jour (si un seul produit).
--------------------------------------
Code : P2
Nom :  Test...
--------------------------------------


 
 
Edit : Plus je me relis, et plus je me dis que c'est total n'imp' mon objet "Produit" :D M'enfin t'as le principe, et il marche ;)
 
On voit notamment très bien dans cet exemple que :
- DataBase ne sais absolument pas ce qu'il fait. Il est complètement générique, et ne contient aucune information relative aux métiers
- On voit aussi que l'objet métier ne sait pas non plus d'où viennent les données et ce qu'on en fait
 
=> En quelques heures, je peux altérer mon objet "DataBase" pour passer à une base Oracle par exemple, ou même la gestion d'information à partir de fichiers XML


Message édité par MagicBuzz le 05-07-2007 à 21:05:46
n°1583072
j_v_e_t
Posté le 06-07-2007 à 08:26:45  profilanswer
 

Merci beaucoup MagicBuzz, c'est exactement ce genre de réponse que j'attendais. Bravo pour la précision de tes explications et pour ton code qui m'a aidé à refaire mon programme proprement et plus efficacement.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  objets métiers -> base de données

 

Sujets relatifs
[ WaitForMultipleObjects ] Lister tous les objets signales ?Base de donnée native
[SQL Server 2005] Restauration d'une table dans une autre[RESOLU] Une liste de pays dans ma base de données SQL
Problème de copier coller de données depuis un classeur fermé.Synchroniser un base de données vers un fichier XML
[MSSQL] Exporter / Importer une base de donnéeRécupérer des données depuis une feuil excel.
Plus de sujets relatifs à : objets métiers -> base de données


Copyright © 1997-2018 Hardware.fr SARL (Signaler un contenu illicite) / Groupe LDLC / Shop HFR