IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entity Framework Discussion :

Manager générique pour gérer le CRUD de classes dérivées


Sujet :

Entity Framework

  1. #1
    Expert éminent
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Points : 9 506
    Points
    9 506
    Par défaut Manager générique pour gérer le CRUD de classes dérivées
    Salut,

    J'ai une classe de base et des dérivées. EF:
    • créé une table pour chaque objet;
    • me permet de mettre à jour les entités à partir de la table de base.


    Constat: le code est le même pour réaliser les opérations du CRUD sur les classes enfant seul le Type à traiter change.

    Question: comment réaliser un manager générique acceptant n'importe lequel des objets?

    Le model:
    Le code:
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
     
    namespace WebApplication1
    {
        public class VehiculeManager : IDisposable
        {
            private Model1Container m = new Model1Container();
     
            public void Create(Volant volant)
            {
                m.VehiculeJeu.AddObject(volant);
                m.SaveChanges();
            }
     
            public Volant Read(int id)
            {
                return m.VehiculeJeu.OfType<Volant>().Where(x => x.ID == id).FirstOrDefault();
            }
     
            public void Dispose()
            {
                m.Dispose();
            }
        }
     
        public partial class _Default : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                using (var mgr = new VehiculeManager())
                {
                    Volant v1 = new Volant();
                    v1.Nom = "747";
                    v1.ModePropulsion = "Réacteur";
                    mgr.Create(v1);
     
                    var v2 = mgr.Read(v1.ID);
     
                    Response.Write(v2.ModePropulsion + "<br />");
                }
            }
        }
    }
    Merci d'avance pour vos idées.

    Petite précision suplémentaire, le manager doit implémenter une interface ICrud comme celle-ci: http://immobilis.developpez.com/tuto...work/#LIII-A-2
    Images attachées Images attachées  
    "Winter is coming" (ma nouvelle page d'accueil)

  2. #2
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    1 377
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 377
    Points : 1 628
    Points
    1 628
    Par défaut
    Bonjour Immobilis,

    Quand tu dis manager ici, c'est un peu le pattern repository non ? Si c'est le cas une solution courante est d'avoir un Repository générique, dont voici un exemple :

    Code c# : 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
    27
    28
    29
    30
    31
     
        public abstract class Repository<T> where T : class
        {
            protected DbContext Context;
            public Repository(DbContext context)
            {
                Context = context;
            }
     
            public virtual IEnumerable<T> GetAll()
            {
                return Context.Set<T>();
            }
     
            public abstract T GetById(int id);
     
            public virtual IEnumerable<T> Query(Expression<Func<T, bool>> filter)
            {
                return Context.Set<T>().Where(filter);
            }
     
            public void Add(T entity)
            {
                Context.Set<T>().Add(entity);
            }
     
            public void Remove(T entity)
            {
                Context.Set<T>().Remove(entity);
            }
        }
    Échouer, c'est avoir la possibilité de recommencer de manière plus intelligente.

    Twitter Blog Mon site

    Mon article sur l'agilité

  3. #3
    Expert éminent
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Points : 9 506
    Points
    9 506
    Par défaut
    Salut,

    Merci de ta réponse c'est une possibilité. Cependant, j'aimerai éviter l'utilisation d'une classe abstraite au profit d'une interface.

    En utilisant la classe de base ça passe, mais cela m'oblige à la convertir lors de la lecture:
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    public interface ICrud<T> : IDisposable
    {
        void Create(T volant);
        T Read(int id);
    }
     
    public class VehiculeManager : ICrud<Vehicule>
    {
        private Model1Container m = new Model1Container();
     
        public void Create(Vehicule vehicule)
        {
            m.VehiculeJeu.AddObject(vehicule);
            m.SaveChanges();
        }
     
        public Vehicule Read(int id)
        {
            return m.VehiculeJeu.Where(x => x.ID == id).FirstOrDefault();
        }
     
        public void Dispose()
        {
            m.Dispose();
        }
    }
     
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            using (var mgr = new VehiculeManager())
            {
                Volant v1 = new Volant();
                v1.Nom = "Cessna";
                v1.ModePropulsion = "Hélice";
                mgr.Create(v1);
     
                var v2 = mgr.Read(v1.ID);
     
                Response.Write((v2 as Volant).ModePropulsion + "<br />");
            }
        }
    }
    Je préférerai manipuler uniquement des interfaces.
    "Winter is coming" (ma nouvelle page d'accueil)

  4. #4
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    1 377
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 377
    Points : 1 628
    Points
    1 628
    Par défaut
    Citation Envoyé par Immobilis Voir le message
    Salut,

    Merci de ta réponse c'est une possibilité. Cependant, j'aimerai éviter l'utilisation d'une classe abstraite au profit d'une interface.

    En utilisant la classe de base ça passe, mais cela m'oblige à la convertir lors de la lecture:
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    public interface ICrud<T> : IDisposable
    {
        void Create(T volant);
        T Read(int id);
    }
     
    public class VehiculeManager : ICrud<Vehicule>
    {
        private Model1Container m = new Model1Container();
     
        public void Create(Vehicule vehicule)
        {
            m.VehiculeJeu.AddObject(vehicule);
            m.SaveChanges();
        }
     
        public Vehicule Read(int id)
        {
            return m.VehiculeJeu.Where(x => x.ID == id).FirstOrDefault();
        }
     
        public void Dispose()
        {
            m.Dispose();
        }
    }
     
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            using (var mgr = new VehiculeManager())
            {
                Volant v1 = new Volant();
                v1.Nom = "Cessna";
                v1.ModePropulsion = "Hélice";
                mgr.Create(v1);
     
                var v2 = mgr.Read(v1.ID);
     
                Response.Write((v2 as Volant).ModePropulsion + "<br />");
            }
        }
    }
    Je préférerai manipuler uniquement des interfaces.
    La mettre abstraite c'était un exemple

    Dans mon projet, on a une interface IRepository<T> (l'équivalent de ICrud) et une classe Repository<T> qui fais la même chose

    [Edit] Après une rapide recherche voici un exemple pour illustrer mon propos :
    http://elegantcode.com/2009/12/15/en...ork-prototype/

    A+
    Échouer, c'est avoir la possibilité de recommencer de manière plus intelligente.

    Twitter Blog Mon site

    Mon article sur l'agilité

  5. #5
    Expert éminent
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Points : 9 506
    Points
    9 506
    Par défaut
    OK, nous ne sommes pas tout à fait sur les mêmes bases. Il faut déjà que j'installe cette version 4.1 du Framework 4. Je teste et te dit.
    "Winter is coming" (ma nouvelle page d'accueil)

  6. #6
    Expert éminent
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Points : 9 506
    Points
    9 506
    Par défaut
    D'ailleurs, si tu as une idée pour implémenter cela avec le FW 4.0 ça me va.
    "Winter is coming" (ma nouvelle page d'accueil)

  7. #7
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    1 377
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 377
    Points : 1 628
    Points
    1 628
    Par défaut
    C'est un peu la même chose, il faut juste modifier les api's :

    Au lieu de DbContext -> ObjectContext
    Au lieu de Set<> -> ObjectSet<>
    Au lieu de Add -> AddObject

    Pour créer un ObjectSet il faut passer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _objectSet = context.CreateObjectSet<T>();
    (le code dans le site c EF 4.0 me semble-t-il)

    Ex tirer de la msdn :

    Code c# : 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
    public class SqlRepository<T> : IRepository<T>
                                    where T : class, IEntity {
        public SqlRepository(ObjectContext context) {
            _objectSet = context.CreateObjectSet<T>();
        }
        public IQueryable<T> FindAll() {
            return _objectSet;
        }
        public IQueryable<T> FindWhere(
                               Expression<Func<T, bool>> predicate) {
            return _objectSet.Where(predicate);
        }
        public T FindById(int id) {
            return _objectSet.Single(o => o.Id == id);
        }
        public void Add(T newEntity) {
            _objectSet.AddObject(newEntity);
        }
        public void Remove(T entity) {
            _objectSet.DeleteObject(entity);
        }
        protected ObjectSet<T> _objectSet;
    }

    http://msdn.microsoft.com/en-us/library/ff714955.aspx
    Échouer, c'est avoir la possibilité de recommencer de manière plus intelligente.

    Twitter Blog Mon site

    Mon article sur l'agilité

  8. #8
    Expert éminent
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Points : 9 506
    Points
    9 506
    Par défaut
    Merki!

    Voici ton code (un poil modifié) + le mien:
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    using System;
    using System.Data.Objects;
    using System.Linq;
    using System.Linq.Expressions;
     
    namespace WebApplication1
    {
        public interface IEntity
        {
            int ID { get; set; }
        }
     
        public interface ICrud<T> : IDisposable where T : class
        {
            IQueryable<T> FindAll();
            IQueryable<T> FindWhere(Expression<Func<T, bool>> predicate);
            T FindById(int id);
            void Add(T newEntity);
            void Remove(T entity);
        }
     
        public class Repository<T> : ICrud<T> where T : class, IEntity
        {
            private ObjectSet<T> _objectSet;
            private ObjectContext _context = new Model1Container();
            private bool disposed = false;
     
            public Repository()
            {
                _objectSet = _context.CreateObjectSet<T>();
            }
            public IQueryable<T> FindAll()
            {
                return _objectSet;
            }
            public IQueryable<T> FindWhere(Expression<Func<T, bool>> predicate)
            {
                return _objectSet.Where(predicate);
            }
            public T FindById(int id)
            {
                return _objectSet.Single(o => o.ID == id);
            }
            public void Add(T newEntity)
            {
                _objectSet.AddObject(newEntity);
            }
            public void Remove(T entity)
            {
                _objectSet.DeleteObject(entity);
            }
            public void Save()
            {
                _context.SaveChanges();
            }
            #region IDisposable
            public void Dispose()
            {
                if (!disposed)
                {
                    Dispose(true);
                    GC.SuppressFinalize(this);
                }
                disposed = true;
            }
            ~Repository()
            {
                Dispose(false);
            }
            private void Dispose(bool disposing)
            {
                if (disposing)
                {
                    _objectSet = null;
                    _context.Dispose();
                    _context = null;
                }
            }
            #endregion
        }
     
        partial class Vehicule : IEntity
        { }
     
        public partial class _Default : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                using (var repository = new Repository<Vehicule>())
                {
                    Volant v1 = new Volant();
                    v1.Nom = "Parachute ascensionnel";
                    v1.ModePropulsion = "Bateau";
                    repository.Add(v1);
                    repository.Save();
     
                    var v2 = repository.FindById(v1.ID);
                    Response.Write((v2 as Volant).ModePropulsion + "<br />");
                }
            }
        }
    }
    Faudra que je teste les perfs de tout ça.

    A+
    "Winter is coming" (ma nouvelle page d'accueil)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 04/05/2007, 14h10
  2. Réponses: 3
    Dernier message: 05/10/2006, 17h15
  3. Utilisation de classes pour gérer une table
    Par mathias dans le forum Access
    Réponses: 11
    Dernier message: 30/08/2006, 16h57
  4. Réponses: 1
    Dernier message: 20/08/2006, 13h36
  5. [DOM XML] Classe pour gérer du xml
    Par __fabrice dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 29/05/2006, 14h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo