none
ASP.NET et variables partagées RRS feed

  • Question

  • Bonjour,

    Je travaille sur un site web en ASP mais je rencontre quelques difficultés.

    Mon site utilise une librairie de classes qui représente ma BDD avec Entity Framework.

    Mon truc est que je voudrais savoir si c'est normal que toutes les sessions partagent le même objet ou pas ? S'agit-il du comportement habituel ou alors il faut revoir certains trucs ?

    Disons que j'appelle ma BDD via un Objet DataAccess.EntitieContext.Context qui n'est autre qu'un Singleton définit de la manière suivante.


      private static EntitiesContext _Context = null;
            public static EntitiesContext Context
            {
                get { 
                    
                    if(_Context == null)
                    {
                        try
                        {
                            
                            EFTracingProviderConfiguration.LogToConsole = false;
                            EFTracingProviderConfiguration.LogToFile = SqlLogFile;
    
                            EFCachingProviderConfiguration.DefaultCachingPolicy = CachingPolicy.CacheAll;
                            EFCachingProviderConfiguration.DefaultCache = new InMemoryCache();
    
    
                            if (Tracing)
                            {
                                EFTracingProviderConfiguration.RegisterProvider();
                            }
    
                            if (Caching)
                            {
                                EFCachingProviderConfiguration.RegisterProvider();
                            }
    
    
                            if (string.IsNullOrEmpty(ConnectionString))
                            {
                                _Context = new EntitiesContext();
                            }
                            else
                            {
                                if (Tracing || Caching)
                                {
                                    List<string> Param = new List<string>();
                                    if (Tracing)
                                    {
                                        Param.Add("EFTracingProvider");
                                    }
    
                                    if (Caching)
                                    {
                                        Param.Add("EFCachingProvider");
                                    }
    
                                    _Context = new EntitiesContext(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
                                                        ConnectionString,
                                                        Param.ToArray()));
                                }
                                else
                                {
                                    _Context = new EntitiesContext(ConnectionString);
                                }
                            }
                        }
                        catch 
                        {
                            throw;
                        }
    
                        _Context.Adresses.MergeOption = MergeOption.PreserveChanges;
                        _Context.CommunauteAgglomerations.MergeOption = MergeOption.PreserveChanges;
                        _Context.Communes.MergeOption = MergeOption.PreserveChanges;
    
                        _Context.Personnes.MergeOption = MergeOption.PreserveChanges;
                        _Context.Enfants.MergeOption = MergeOption.PreserveChanges;
    
                        _Context.Presences.MergeOption = MergeOption.PreserveChanges;
                        _Context.DemandeConges.MergeOption = MergeOption.PreserveChanges;
    
                        _Context.Affaires.MergeOption = MergeOption.PreserveChanges;
                        _Context.OrdreDeMissions.MergeOption = MergeOption.PreserveChanges;
                        _Context.ListeOptionOrdreDeMissions.MergeOption = MergeOption.PreserveChanges;
    
                        _Context.LienOrdreDeMissionArchivageFichiers.MergeOption = MergeOption.PreserveChanges;
    
                        _Context.Clients.MergeOption = MergeOption.PreserveChanges;
    
    
                        _Context.CommandeFournisseurLignes.MergeOption = MergeOption.PreserveChanges;
                        _Context.CommandeFournisseurs.MergeOption = MergeOption.PreserveChanges;
    
                    }
                    return _Context; 
                }
            }

    Ce qui me permet donc de dire que l'objet est donc partagé entre toutes les sessions. Cela est-il normal dans le développement d'un site web asp ?

    L'objet ne doit-il pas être différent entre chaque user du site ?


    mercredi 18 mars 2015 10:37

Réponses

  • Bonjour,

    Effectivement vous allez avoir un problème en utilisant un DBContext partagé (singleton, statique ou autre).

    Dans le cadre d'une application pouvant avoir n users connectés en simultanés, il ne faut jamais utiliser un DBContext partagé car des problèmes d'accès concurrent au DBContext vont survenir.

    Je vous conseille de créer un DBContext à chaque fois que vous avez besoin d'accèder à la base de données en pensant à le disposer dès que vous aller sortir de votre méthode.

    Exemple :

    using (DbContext db = new DbContext)

    {

        return db.Table.List();

    }

    Cordialement,

    Mathieu


    Mathieu Notin

    mercredi 18 mars 2015 12:40
  • Bonjour,

    Oui c'est ce que cela veut dire. C'est l'une des problématique d'entity Framework (même si les perfs se sont nettement amélioré de version en version).

    Il est possible de garder un DbContext en session, toutefois attention :

    - Si une autre session met à jour votre base de données, est ce que le dbcontext de la première session sera mise à jour ?

    - Même si le dbcontext est mis à jour à chaque update de base, vous risquez de consommer énormément de mémoire pour maintenir les dbcontext de chaque session ouverte.

    Je reste sur mon premier conseil, le using de dbcontext quand vous en avez besoin (et uniquement quand vous en avez besoin) même s'il doit y avoir des solutions d'optimisations pour éviter certains problèmes de perf (mais je ne les connais pas ^^).

    Cordialement,

    Mathieu


    Mathieu Notin

    • Marqué comme réponse Lionhart34 mardi 24 mars 2015 12:14
    lundi 23 mars 2015 09:06

Toutes les réponses

  • Bonjour,

    Effectivement vous allez avoir un problème en utilisant un DBContext partagé (singleton, statique ou autre).

    Dans le cadre d'une application pouvant avoir n users connectés en simultanés, il ne faut jamais utiliser un DBContext partagé car des problèmes d'accès concurrent au DBContext vont survenir.

    Je vous conseille de créer un DBContext à chaque fois que vous avez besoin d'accèder à la base de données en pensant à le disposer dès que vous aller sortir de votre méthode.

    Exemple :

    using (DbContext db = new DbContext)

    {

        return db.Table.List();

    }

    Cordialement,

    Mathieu


    Mathieu Notin

    mercredi 18 mars 2015 12:40
  • Bonjour,

    Cela veut donc dire qu'à chaque chargement de page (et usage de bouton) je créer un nouveau context ?

    Et donc je fini par faire dispose à la fin du chargement ?

    Ma dernière question : N'est-il pas possible de garder mon dbContext dans une session ?


    Merci, pour ces premiers éléments de réponses.
    lundi 23 mars 2015 08:33
  • Bonjour,

    Oui c'est ce que cela veut dire. C'est l'une des problématique d'entity Framework (même si les perfs se sont nettement amélioré de version en version).

    Il est possible de garder un DbContext en session, toutefois attention :

    - Si une autre session met à jour votre base de données, est ce que le dbcontext de la première session sera mise à jour ?

    - Même si le dbcontext est mis à jour à chaque update de base, vous risquez de consommer énormément de mémoire pour maintenir les dbcontext de chaque session ouverte.

    Je reste sur mon premier conseil, le using de dbcontext quand vous en avez besoin (et uniquement quand vous en avez besoin) même s'il doit y avoir des solutions d'optimisations pour éviter certains problèmes de perf (mais je ne les connais pas ^^).

    Cordialement,

    Mathieu


    Mathieu Notin

    • Marqué comme réponse Lionhart34 mardi 24 mars 2015 12:14
    lundi 23 mars 2015 09:06
  • Bonjour,

    J'ajoute une précision, c'est la méthode préconisée pour la gestion des données en ADO.NET (même hors de EF) que d'ouvrir une connexion dans un cours laps de temps, et donc de l'intégrer dans un "using".

    EF ne fait qu'appliquer cette recommandation.

    Cela ne pose de gros problème de performance car ADO.NET utilise un pool de connexion, qui réutilise une connexion récemment ouverte.

    Cordialement,


    Yan Grenier

    Merci de bien vouloir "Marquer comme réponse", les réponses qui ont répondues à votre question, et de noter les réponses que vous avez trouvé utiles.

    lundi 23 mars 2015 09:43
  • Ok,

    Merci pour toutes vos recommandations.

    Je vais mettre cette solution en place.


    mardi 24 mars 2015 12:13