Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

COUCHE D'ACCÈS AUX DONNÉES SIMPLIFIÉE


Information sur la source

Catégorie :Base de données Source .NET ( DotNet ) Classé sous : données, objet, couche, accès Niveau : Expert Date de création : 04/01/2008 Vu / téléchargé: 5 866 / 424

Note :
10 / 10 - par 1 personne
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (5)
Ajouter un commentaire et/ou une note


Description

Un jour où j'avais un peu de temps libre, je me suis dis, "Et si je réinventais la roue ?". Appliqué dans ce cas, je me suis demandé comment pourrais-je faire pour créer une librairie d'accès aux données qui soit complètement objet, et qui permette de s'affranchir au maximum du type de SGBD sous-jacent...

Voici le résultat de mon travail.

Le moteur se compose de plusieurs classes :
  - Une classe de base pour les données (sérialisable, avec INotifyPropertyChanged)
  - Une classe pour implémenter les fonctions minimales requises pour accéder à un SGBD
  - Une classe qui permet de faire les requêtes dans la base (insert, update, delete, select)
  - Des classes pour définir ces requêtes

Pour définir une donnée (ou entité), on crée une classe qui hérite de ClsBusinessEntity. Elle possède un attribut BusinessTable pour définir à quel table elle appartient. Chacune de ses propriétés possède un attribut BusinessField pour définir le champ de la table (nom du champ, type de donnée, longueur). Si le champ est une clé primaire, on ajoute l'attribut BusinessKeyField. Si c'est un Guid, on met l'attribut BusinessGUID (le traitement est légèrement différent).

Pour accéder à la base de données, on instancie une classe d'accès aux données, qui implémente ClsBusinessDataLayer<TProvider>, qui elle-même utilise Ado.net pour faire la liaison.

Pour utiliser les données, on doit créer un "moteur" pour y accéder. On instancie un ClsBusinessEngine<TEntity, TLayer> où TEntity est le type de l'entité à gérer et TLayer le type de la couche d'accès aux données (ClsBusinessDataLayer).

Après, tout se fait tout seul (ou presque), un petit exemple est fourni, avec une implémentation pour MySql.
 

Source

  • using System;
  • using System.Collections.Generic;
  • using System.Text;
  • using System.Data;
  • namespace MaitreDede.DataAccess.Example
  • {
  • /*
  • * CREATE TABLE table_test (
  • * id VARCHAR(36) NOT NULL PRIMARY KEY COMMENT '[GUID]',
  • * nom VARCHAR(255) NOT NULL
  • * );
  • */
  • [BusinessTable("table_test")]
  • [Serializable]
  • public sealed class ClsTest:ClsBusinessEntity
  • {
  • private Guid _id;
  • private string _nom;
  • [BusinessField("id",DbType.Guid,36)]
  • [BusinessGUID]
  • [BusinessKeyField]
  • public Guid Id { get { return this._id; } set { this._id = value; base.Changed(); } }
  • [BusinessField("nom",DbType.StringFixedLength,255)]
  • public string Nom { get { return this._nom; } set { this._nom = value; base.Changed(); } }
  • }
  • class Program
  • {
  • static void Main(string[] args)
  • {
  • string connectionString = "host=localhost;user=test;password=test;base=test";
  • //Création de la couche d'accès aux données
  • ClsBusinessDataLayerMysql layer = new ClsBusinessDataLayerMysql(connectionString);
  • //Création du wrapper pour les ClsTest
  • ClsBusinessEngine<ClsTest, ClsBusinessDataLayerMysql> testWrapper = new ClsBusinessEngine<ClsTest, ClsBusinessDataLayerMysql>(layer);
  • //Création de quelques classes de données
  • ClsTest tst1 = new ClsTest();
  • tst1.Id = Guid.NewGuid();
  • tst1.Nom = "Test1";
  • ClsTest tst2 = new ClsTest();
  • tst2.Id = Guid.NewGuid();
  • tst2.Nom = "Test2";
  • //Insertion des données
  • testWrapper.Insert(tst1);
  • testWrapper.Insert(tst2);
  • //Création d'une requête : je sélectionne toutes les ClsTest qui ont un nom égal à 'Test2'
  • //On récupère la définition du champ via le nom de la propriété
  • ClsBusinessFieldDefinition defChampNom = testWrapper["Nom"];
  • //Création de l'opérande "champ de table"
  • ClsOperandField champNom = new ClsOperandField(defChampNom);
  • //Création de l'opérande "paramètre" (pour ajouter des constantes à la requête)
  • ClsOperandParameter valeurChamp = new ClsOperandParameter(defChampNom, "Test2");
  • //Création de la clause complète
  • ClsBusinessQueryOperation clause = new ClsBusinessQueryOperation(ClsOps.Equal, champNom, valeurChamp);
  • //Au final, on a fait une condition : table_test.nom = 'Test2'
  • //On sélectionne les données selon ce filtre
  • ClsBusinessDataReader<ClsTest> dataReader = testWrapper.Select(clause);
  • //On lit le datareader
  • while (dataReader.Read())
  • {
  • //On récupère la ligne courante
  • ClsTest entity = dataReader.GetEntity();
  • //On en fait ce qu'on veux
  • Console.WriteLine("id:" + entity.Id + " nom:" + entity.Nom);
  • }
  • dataReader.Close();
  • }
  • }
  • }
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace MaitreDede.DataAccess.Example
{
    /*
     * CREATE TABLE table_test (
     *      id VARCHAR(36) NOT NULL PRIMARY KEY COMMENT '[GUID]',
     *      nom VARCHAR(255) NOT NULL
     *  );
     */
    [BusinessTable("table_test")]
    [Serializable]
    public sealed class ClsTest:ClsBusinessEntity
    {
        private Guid _id;
        private string _nom;

        [BusinessField("id",DbType.Guid,36)]
        [BusinessGUID]
        [BusinessKeyField]
        public Guid Id { get { return this._id; } set { this._id = value; base.Changed(); } }

        [BusinessField("nom",DbType.StringFixedLength,255)]
        public string Nom { get { return this._nom; } set { this._nom = value; base.Changed(); } }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string connectionString = "host=localhost;user=test;password=test;base=test";
            
            //Création de la couche d'accès aux données
            ClsBusinessDataLayerMysql layer = new ClsBusinessDataLayerMysql(connectionString);

            //Création du wrapper pour les ClsTest
            ClsBusinessEngine<ClsTest, ClsBusinessDataLayerMysql> testWrapper = new ClsBusinessEngine<ClsTest, ClsBusinessDataLayerMysql>(layer);

            //Création de quelques classes de données
            ClsTest tst1 = new ClsTest();
            tst1.Id = Guid.NewGuid();
            tst1.Nom = "Test1";
            ClsTest tst2 = new ClsTest();
            tst2.Id = Guid.NewGuid();
            tst2.Nom = "Test2";

            //Insertion des données
            testWrapper.Insert(tst1);
            testWrapper.Insert(tst2);

            //Création d'une requête : je sélectionne toutes les ClsTest qui ont un nom égal à 'Test2'
            //On récupère la définition du champ via le nom de la propriété
            ClsBusinessFieldDefinition defChampNom = testWrapper["Nom"];
            //Création de l'opérande "champ de table" 
            ClsOperandField champNom = new ClsOperandField(defChampNom);
            //Création de l'opérande "paramètre" (pour ajouter des constantes à la requête)
            ClsOperandParameter valeurChamp = new ClsOperandParameter(defChampNom, "Test2"); 
            //Création de la clause complète
            ClsBusinessQueryOperation clause = new ClsBusinessQueryOperation(ClsOps.Equal, champNom, valeurChamp);
            //Au final, on a fait une condition : table_test.nom = 'Test2'

            //On sélectionne les données selon ce filtre
            ClsBusinessDataReader<ClsTest> dataReader = testWrapper.Select(clause);
            //On lit le datareader
            while (dataReader.Read())
            {
                //On récupère la ligne courante
                ClsTest entity = dataReader.GetEntity();

                //On en fait ce qu'on veux
                Console.WriteLine("id:" + entity.Id + " nom:" + entity.Nom);
            }
            dataReader.Close();
        }
    }
}

Conclusion

Ma librairie offre beaucoup de possibilités, tant qu'on n'utilise pas de trucs trop "tordus".

Je l'ai implémenté pour MySql (fourni), mais aussi pour OleDb et SqlServer.

J'ai aussi fait une appli qui utilise cette librairie, et où la personne qui configure l'application peut choisir sur quelle base de données l'application doit tourner.
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Commentaires et avis

signaler à un administrateur
Commentaire de tmcuh le 04/01/2008 11:51:13

Idée original et bien développé, enfin pour le code que tu propose en exemple :) ... j'ai pas encore testé le projet, mais je met 10 pour l'initiative.
Il aurait été simpa de crée la class "ClsTest" de façon entièrement dynamique ce qui permettrait d'avoir un VRAI objet complètement autonome quelque soit la situation et avoir ainsi une dll qui se charge de "tout" pour l'accès au données et renseignement des champs, tables, type, etc.

amicalement,
Tmcuh

signaler à un administrateur
Commentaire de tmcuh le 04/01/2008 11:51:34 10/10

J'oublié la note ^^

signaler à un administrateur
Commentaire de maitredede le 04/01/2008 12:02:33

@Tmcuh : Merci pour ton soutient :)

L'idée de créer la classe teste en dynamique est presque possible, une classe non documentée est ClsBusinessCodeGenerator, qui permet de créer le code des classes à partir de la structure des tables. Elle n'est pas encore parfaite, mais elle existe.

Après, je peux partir autrement (dictionnaire champ/valeur) mais pour l'instant, je n'en ai pas l'utilité. Si des personnes me le demande, je l'implémenterai.

Amicalement,
Dédé

signaler à un administrateur
Commentaire de slars le 30/04/2008 14:33:57

salut
j'ai un problème avec les DBNULL dans un datagridview
en fait j'ai ajouter une table dans ma base de données SQL Server2000 et je l'ai lié à un datagrid view, kon j'ajoute une nouvelle ligne par AddNew du binding source la cellule du ID ne se rempli pa alors k dans d'otre table elle se rempli

sauvez moi SVP

signaler à un administrateur
Commentaire de tmcuh le 30/04/2008 14:47:43

Elle ne se rempli automatiquement que si le champs est marqué comme tel ("Autoincrement")

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

développer en couche [ par zoplaka ] Bonjour à tous, je suis debutant et j'ai la responsabilité de développer une application en c# en utilisant le developpement en couche. Je dois utilis enregistrement de données de type "Objet-OLE" sous Access [ par boutonk ] Bonjour tout le monde,Voici mon probl&#232;me: J'ai un programme &#233;crit en C#&nbsp;qui enregistre des donn&#233;es de type byte[] dans une table d Base de données + Meilleur solutions [ par emmanuel9 ] Bonjour &#224; tous, - J'ai une base de donn&#233;es avec dedans des tables : "Personne" "Soci&#233;t&#233;" "Categorie". - J 'ai une application Controle d'accessibilité d'une méthode / propriété [ par thiosyiasar ] Bonjour a tous !Voila mon PB:J'ai deux assembly :Un pour l'accès aux données.Un autre contenant les entitésLa couche d'accès aux données communique vi accès aux bases de données [ par 17182 ] salut, je veux faire une insertion des données à partir d'une formulaire qui contient des textbox, des boutons radio, des checkbox et des dropdownlist DataGridView et insertion des données dans la BD [ par etoiledevie ] magicBonjour,Dans mon application, j'ai une fenètre contenant un dataGridview permettant l'affichage des données à partir d'une BD oracle 9i et je peu EventLog [ par hassene85 ] Bonjour tout le monde,Je veux créer une application qui permet d'envoyer les données provenant du journal d'evénement windows(EventLog)  .Je veux alor EventLog socket [ par hassene85 ] Je veux créer une application avec les sockets qui permet d'envoyer les données depuis  le journal des évenêments de windows à un serveur d'ecoute.exe Acces à un dossier partagé via une application seulement [ par oximoron ] Voilà je me résigne car je ne trouve pas de réponse à mon problème. Ca n'est pas faute d'avoir cherché mais là ...Voici mon  problème, j'ai un serveur


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,905 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.