[Linq to SQL] - Récursivité

Bonjour à tous,

Alors voilà, je (re)commence à jouer avec Linq et Linq to SQL en ce moment.

J’ai une petite question :

Je souhaiterai faire une requête récursive. Voilà, j’ai une table (T_ITEMS) avec une relation récursive :

[codebox]T_ITEMS

ItemID
ParentItemID
TitleItem[/codebox]

Or je ne vois pas très bien comment faire cette requête avec Linq. J’ai commencé à chercher et j’ai trouvé
ça

Malheureusement je ne comprends pas très bien et le code associé ne m’aide pas vraiment. Je me suis dis que d’autres étaient peut-être dans le même cas que moi alors…

Ce que j’ai compris c’est qu’on peut grouper les données projetées en fonction d’un élément :

[codebox]var query = from i in Items
group i by i.ParentRubriqueID into g
select g[/codebox]

En revanche pour récupérer ces données de façon typées , je suis un peu paumé.

Merci d’avance :slight_smile:

Si je ne suis pas assez clair, faites moi signe !

Sinon t’es sous quel SGBD ? Sous Oracle tu as CONNECT BY par exemple.

Bonsoir,

Sql server 2005 Express Edition mais je pense que ça n’a pas d’importance puisqu’en fait c’est la “requête” Linq que je cherche et c’est le moteur qui va la transformer en requête SQL.

[quote=« EzecKiel, post:3, topic: 47254 »]c’est la « requête » Linq que je cherche[/quote]Je m’en doutais un peu :slight_smile:

Si t’as juste un niveau de profondeur ou un truc sans branches, ok, mais sinon si c’est tout une arborescence, je pense que c’est pas la maniere optimale de stocker un arbre dans une SGBD surtout :slight_smile:

En fait je n’aurai que 3 ou 4 noeuds par niveau max et 3 niveau de profondeur.
Mais c’est aussi pour « l’exercice », et comprendre la syntaxe :slight_smile:

Si tu as utilisé l’outils de génération de classes Linq To SQL, il a du te générer des propriétés ParentCategory et ChildrenCategories (le nom des propriétés n’est pas garanti ^^), permettant d’accéder aux entitées reliées et poser des contraintes dessus.
Par défaut, les entitées reliées sont chargées en mode “Lazy Loading”, c’est à dire qu’une requète est effectuée au moment ou l’on veut y accéder. Cependant, on peut modifier ce comportement grâce aux “DataLoadOptions” du DataContext.
De mémoire, le code doit ressembler plus ou moins à ca:

var options = new DataLoadOptions();
options.LoadWith((Category cat)=>cat.ChildrenCategories);
myContext.DataLoadOptions = options;

Il doit y avoir aussi un moyen, dans le cas où le LoadWith est récursif, d’indiquer le nombre maximal de récursions à effectuer.

ensuite, tu vas pouvoir faire:

var rootCategories = from cat in ctx.Categories
where cat.ParentCategory == null
select cat;

Et voilà, tu as tes catégories racines, avec les “ChildrenCategories” préchargées.

Ok, merci je vais regarder ça de près.

Une autre précision : je voulais ‹ isoler › cette méthode dans la couche d’accès aux données de mon appli. Pour ce faire, j’ai rajouté une classe partielle dans mon datacontext (ça sonne faut mais vous comprendrez l’idée) dans laquelle j’ai rajouté ma méthode.

1°) Est-ce que ça se fait / est-ce la bonne manière ?
2°) C’est pour ça que j’ai quelques petits soucis (je ne peux pas utiliser de types anonymes par exemple).

Je reviens vers vous dès que j’aurai avancé sur le sujet.

Merci en tout cas :slight_smile:

Ca se fait et c’est une relativement bonne chose, car la génération des requêtes SQL est le rôle de la couche d’accès aux données. Moins tes IQueryable sont visibles des couches supérieures, et mieux tu te portes.

Maintenant, le soucis, c’est que forcément, si tu étends le DataContext par partialité, ca veut dire que ta couche du dessus doit connaitre ta classe DataContext, donc peut utiliser directement les “IQueryable”.

Bonjour !

bon alors je viens d’essayer ça :

et en fait il me jette une belle exception au runtime :

System.InvalidOperationException was unhandled Message="Cycles non autorisés dans le graphique de type LoadOptions LoadWith." System.Data.Linq.DataLoadOptions.ValidateTypeGraphAcyclic()

Apparement il ne gère pas la récursivité…

PS : Le nom des propriétés générées est assez bizarre, pour le parent il met [nom_entité]1 et pour les enfants [nom_entité]s (sans les crochets). Elles sont évidemment modifiables.

Dans ce cas tu peux faire un truc du genre:
from i in ctx.Items
where i.Parent == null
select new { Item = i, Children = from i2 in i.Children
select new{Item = i2, Children= i2.Children};