Chargement dynamique, paresseux et explicite dans EF6

j'ai lu ce tutoriel et cet article mais je ne comprends pas exactement l'utilisation de chaque type de chargement.

J'Explique

j'ai ce POCO:

public partial class dpc_gestion
{
    public dpc_gestion()
    {
        this.ass_reunion_participant = new HashSet<ass_reunion_participant>();
        this.dpc_participant = new HashSet<dpc_participant>();
        this.dpc_reunion = new HashSet<dpc_reunion>();
    }

    public int dpc_id_pk { get; set; }
    public Nullable<int> dpc_id_gdp_fk { get; set; }
    public Nullable<int> dpc_id_theme { get; set; }
    public int dpc_id_animateur_fk { get; set; }
    public Nullable<System.DateTime> dpc_date_creation { get; set; }
    public Nullable<System.DateTime> dpc_date_fin { get; set; }
    public Nullable<System.DateTime> dpc_date_engag_anim { get; set; }
    public Nullable<bool> dpc_flg_let_engag_anim { get; set; }
    public Nullable<bool> dpc_flg_fsoins_anim { get; set; }
    public virtual ICollection<ass_reunion_participant> ass_reunion_participant { get; set; }
    public virtual theme_dpc theme_dpc { get; set; }
    public virtual gdp_groupe_de_pair gdp_groupe_de_pair { get; set; }
    public virtual ICollection<dpc_participant> dpc_participant { get; set; }
    public virtual ICollection<dpc_reunion> dpc_reunion { get; set; }
}

j'ai compris ceci:

  1. pour le chargement paresseux : parce que le chargement est paresseux, si j'appelle le dbset dpc_gestion toutes les propriétés de navigation ne sera pas être chargé. Ce type de chargement est le meilleur en termes de performance et de réactivité. Il est activé par défaut et si je veux le réactiver, je dois définir:

    context.Configuration.ProxyCreationEnabled = true;    
    context.Configuration.LazyLoadingEnabled = true;
    
  2. Pour les désireux de chargement Il n'est pas paresseux: il a chargé toutes les propriétés de navigation lorsque je charge dpc_gestion . Les propriétés de navigation peuvent être chargées en utilisant la méthode include . Pour activer ce type de chargement:

    context.Configuration.LazyLoadingEnabled = false;
    
  3. pour le chargement explicite C'est comme le chargement rapide mais nous utilisons la méthode Load au lieu de include .

Donc je voudrais savoir :

  1. si ce petit CV est vrai ?
  2. si c'est vrai, quelle est la différence entre un chargement enthousiaste et un chargement explicite?
  3. si j'utilise lazy loading et j'appelle par exemple dpc_gestion.dpc_participant , est-ce que les propriétés de navigation se chargent?ou je vais avoir une exception?
  4. y a-t-il un cas où le chargement rapide ou le chargement explicite étaient meilleurs que le chargement paresseux dans la performance et la réactivité?

Merci

20
demandé sur S.Akbari 2016-01-06 10:34:58

3 réponses

si ce petit CV est vrai ?

Oui.

Si c'est vrai, quelle est la différence entre la hâte et le chargement explicite?

Désireux de chargement est le contraire de Lazy loading mais chargement Explicite est similaire à lazy loading , sauf que: vous récupérez explicitement les données correspondantes dans le code; cela ne se produit pas automatiquement lorsque vous accédez à une propriété de navigation. Vous chargez des données liées manuellement en obtenant l'entrée du gestionnaire d'état d'objet pour une entité et en appelant la méthode Collection.Load pour les collections ou la méthode Reference.Load pour les propriétés qui détiennent une entité unique.

à Partir de techblog :

Chargement Rapide:

Chargement rapide est le opposé de chargement paresseux qui est: le processus de chargement d'un ensemble spécifique d'objets liés avec les objets qui ont été explicitement demandée dans la requête.

Chargement Explicite:

chargement explicite est défini comme: lorsque les objets sont retournés par une requête, objets liés ne sont pas chargés en même temps. Par défaut, ils sont pas chargé jusqu'explicitement demandé l'aide de la méthode de la charge sur un propriété de navigation.

et:

si j'utilise un chargement paresseux et que j'appelle par exemple dpc_gestion.dpc_participant , est-ce que les propriétés de navigation se chargent?ou je vais avoir une exception?

vous ne recevez aucune exception et les propriétés de navigation devraient se charger.

y a-t-il un cas où un chargement accéléré ou un chargement explicite était préférable que paresseux chargement de la performance et de réactivité?

eager loading est généralement plus efficace lorsque vous avez besoin des données connexes pour toutes les lignes récupérées de la table primaire. Et aussi quand les relations ne sont pas trop, chargement impatient sera une bonne pratique pour réduire d'autres requêtes sur le serveur. Mais quand vous savez que vous n'aurez pas besoin d'une propriété instantanément alors chargement paresseux peut-être un bon choix. Et aussi chargement impatient est un bon choix dans une situation où votre contexte db serait éliminé et le chargement paresseux ne pourrait plus avoir lieu. Par exemple, considérons ce qui suit:

public List<Auction> GetAuctions()
{
    using (DataContext db = new DataContext())
    {
        return db.Auctions.ToList();
    }
}

après avoir appelé cette méthode, vous ne pouvez pas charger l'entité liée paresseusement parce que le db est disposé et donc le Chargement rapide serait un meilleur choix ici.

une autre chose à noter est: paresseux le chargement produira plusieurs données de chargement SQL tandis que chargement Eager chargera des données avec une demande. chargement rapide est également un bon choix pour résoudre le n+1 sélectionne la question dans ORMs. Regardez ce billet: Quel est le problème n+1 selects?

18
répondu S.Akbari 2018-02-28 19:32:50

questions 1 et 2:

Votre explication de lazy loading et désireux de chargement est correct.

L'utilisation de chargement explicite est un peu différent de ce que tu décrit.

EntityFramework retourne IQueryable des objets, qui contiennent essentiellement la requête à la base de données. Mais ceux-ci ne sont pas exécutés jusqu'à la première le temps qu'ils sont énumérés.

Load exécute la requête de sorte que ses résultats soient stockés localement.

Appeler Load est la même chose que d'appeler ToList et de jeter que List , sans avoir au-dessus de la création de la List .

Question 3:

si vous utilisez un chargement paresseux, EntityFramework s'occupera de charger le propriété de navigation pour vous, donc vous ne recevrez pas d'exception.

Gardez à l'esprit que cela peut prendre un certain temps et vous faire application unresponsive .

Question 4:

dans les cas déconnectés (par exemple application réseau) vous ne peut pas utiliser chargement paresseux , parce que ces objets sont traduits en DTOs et puis pas suivi par EntityFramework .

aussi, si vous savez que vous allez utiliser un propriété de navigation , sa bonne pratique de le charger avidement , de sorte que vous n'avez pas à attendre jusqu'à ce qu'ils soient chargés à partir de la base de données.

Par exemple, disons que vous stockez le résultat dans une liste et le liez à un DataGrid WPF. Si le DataGrid accède à une propriété qui n'est pas encore chargée, l'utilisateur fait l'expérience d'une temporisation notable jusqu'à ce que cette propriété est affichée. En outre, l'application ne répondra pas pendant le temps de chargement (si vous ne chargez pas asynchrone).

5
répondu Domysee 2016-01-06 07:48:08

ici, vous apprendrez à charger explicitement des entités apparentées dans un graphe d'entités. Chargement explicite est valable dans le cœur EF 6 et EF les deux.

même avec le chargement paresseux désactivé (dans EF 6), il est encore possible de charger paresseusement des entités liées, mais cela doit être fait avec un appel explicite. Utilisez la méthode Load() pour charger explicitement les entités liées. Considérons l'exemple suivant.

using (var context = new SchoolContext())
{
     var student = context.Students
                              .Where(s => s.FirstName == "Bill")
                             .FirstOrDefault<Student>();

     context.Entry(student).Reference(s => s.StudentAddress).Load(); 
     // loads StudentAddress
     context.Entry(student).Collection(s => s.StudentCourses).Load(); 
     // loads Courses collection      
}

dans ce qui précède exemple, context.Entry(student).Reference(s => s.StudentAddress).Load() charge l'entité StudentAddress . La méthode Reference() est utilisée pour obtenir un objet de la propriété de navigation de référence spécifiée et la méthode Load() le charge explicitement.

de la même manière, context.Entry(student).Collection(s => s.Courses).Load() charge la collection cours de propriété de navigation de l'entité étudiante. La méthode Collection() obtient un objet qui représente la propriété collection navigation.

la méthode Load() exécute le SQL requête dans la base de données pour obtenir les données et remplir la référence spécifiée ou la propriété de collecte dans la mémoire, comme indiqué ci-dessous. enter image description here

Query (): Vous pouvez également écrire des requêtes LINQ-to-Entities pour filtrer les données avant de les charger. La méthode Query () nous permet d'écrire d'autres requêtes LINQ pour les entités liées afin de filtrer les données liées.

using (var context = new SchoolContext())
{
    var student = context.Students
                    .Where(s => s.FirstName == "Bill")
                    .FirstOrDefault<Student>();

    context.Entry(student)
             .Collection(s => s.StudentCourses)
               .Query()
            .Where(sc => sc.CourseName == "Maths")
            .FirstOrDefault();
}     

In l'exemple ci-dessus, .Collection(s => s.StudentCourses).Query() nous permet d'écrire des requêtes supplémentaires pour l'entité StudentCourses .

1
répondu Ghulam Dastgeer 2018-08-30 06:40:07