Question

Comment vous chargez paresseux listes imbriquées sans exécuter réellement la requête? Prenons un exemple très simple, disons que j'ai:

class CityBlock {
     IList<Building> BuildingsOnBlock;
     Person BlockOwner;
}

class Building {
     IList<Floor> FloorsInBuilding;
}

class Floor {
     IList<Cubicle> EmployeeCubicles;
}

Class Cubicle {
     System.Guid CubicleID;
     Person CubicleOccupant;
}

Et puis dans ma couche dépôt, j'ai la méthode suivante:

GetCityBlocks()

Et puis dans la couche de service, je vais avoir GetCityBlocksByOwner, où j'utiliser une méthode d'extension pour obtenir les blocs de la ville appartenant à une personne en particulier, disons que nous voulons juste les blocs de Guido:

GetCityBlocks().ForOwner("Guido")

Si nous faisons un .ToList () dans le référentiel, il va exécuter les requêtes - qui va être ridicule puisque nous ne savons pas qui est des blocs que nous obtenons à ce niveau. La question est, comment pouvons-nous faire efficacement?

Supposons il y a les propriétaires de blocs 50000 et quelques 1000000 blocs de la ville, le chargement tous est pas une option. Utilisation de IQueryables ne fonctionnera pas en raison de l'imbrication (sans hacking extrême, au moins que je suis au courant). De plus, si je tente d'utiliser quelque chose comme Rob LazyList de Conery, nous avons essentiellement une fuite de notre DAL dans nos modèles de domaine, ce qui pourrait être très très mal à l'avenir.

Alors, comment dois-je procéder correctement?

  • Est-ce une question de détermination de la bon contexte? Si oui, ferions-nous ceci dans la couche du référentiel, ou couche de service?
  • Est-ce que je MELD moitié ensemble de la couche de service et ma couche Repository pour obtenir méthodes de service très spécifique?
  • Ou suis-je manque quelque chose tout à fait? (Encore relativement nouveau pour la Linq2Sql chose, qui est éliminé alors ... de toute façon)

Edit: Dans le modèle référentiel, nous cartographie actuellement à nos objets de domaine, il ressemblerait à quelque chose comme ceci:

public IQueryable<CityBlock> GetCityBlocks(){
    var results = from o in db.city_blocks
                  let buildings = GetBuildingsOnBlock(o.block_id)
                  select new CityBlock {
                      BuildingsOnBlock = buildings,
                      BlockOwner = o.block_owner
                  };
    return results;
}

Pour que cela fonctionne, nous aurions dû faire les bâtiments obtenir un .ToList (), à moins que nous faisons ce champ réel dans l'objet CityBlock IQueryable - ce qui ne semble pas juste, car il semble que trop le pouvoir serait accordé à toute personne qui accède au champ CityBlock.BuildingsOnBlock. Est-ce mapping à notre domaine des objets que nous devrions peut-être faire dans la couche de service?

Était-ce utile?

La solution

Vous le faites en retour IQueryables au lieu de ILists.

ToList () provoque les requêtes à exécuter immédiatement, car une conversion doit être effectuée à partir IQueryable à IList.

Tant que vous retournez IQueryables le chargement paresseux devrait différer l'exécution jusqu'à ce que les données sont réellement nécessaires, à savoir quand ToList () est appelée.

Je ne peux pas trouver une référence au moment, mais je crois savoir que, si vous le faites de cette façon, LINQ to SQL a la possibilité d'optimiser le SQL qu'il envoie au serveur. En d'autres termes, il sera finalement lire ces enregistrements:

GetCityBlocks().ForOwner("Guido")

plutôt que ces enregistrements:

GetCityBlocks()

Autres conseils

Vous pouvez essayer une approche différente dans la cartographie de vos objets de domaine pour le faire fonctionner. Le problème est que peu importe ce que vous faites (sauf si vous modifiez vos listes à IQueryables dans vos objets de domaine), vous finirez par ToList () uant pendant que vous traitez.

L'autre façon à laisser linq2sql faire la mise en correspondance à vos Poços en créant un datacontext personnalisé et ne pas utiliser le concepteur pour la cartographie :), de cette façon vous gardez votre modèle de domaine propre et laissez linq2sql renseigner les dépendances au bon moment . Notez que d'entrer dans cette voie a ses propres problèmes, mais il peut être fait.

Voici un lien pour vous aider à démarrer sur cette route

Réaliser POCO s dans LINQ to SQL

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top