3

J'ai une table des actualités et je souhaite mettre en œuvre une commande personnalisée. Je l'ai fait auparavant via une table de mappage de position qui contient des newsIds et une position.Commande personnalisée Linq to Entities via le tableau de mappage de position

I puis LEFT OUTER JOIN la table de position sur news.newsId = position.itemId avec une instruction select cas

CASE WHEN [position] IS NULL THEN 9999 ELSE [position] END 

et de l'ordre par la position asc, articleDate desc. Maintenant j'essaye de faire la même chose avec Linq aux Entités. J'ai mis en place mes tables avec une relation PK, FK afin que mon objet News dispose d'une collection d'entités de positions.

Maintenant vient le peu que je ne peux pas m'entraîner. Comment implémenter le LEFT OUTER JOIN.

J'ai jusqu'à présent:

var query = SelectMany (n => n.Positions, (n, s) => new { n, s }) 
        .OrderBy(x => x.s.position) 
        .ThenByDescending(x => x.n.articleDate) 
        .Select(x => x.n); 

Cela fonctionne un peu. Cependant, cela utilise un INNER JOIN donc pas ce que je suis après.

J'ai eu une autre idée:

ret = ret.OrderBy(n => n.Positions.Select(s => s.position)); 

Cependant, je reçois l'erreur expressions DbSortClause doit avoir un type qui est l'ordre comparable.

J'ai essayé aussi

ret = ret.GroupJoin(tse.Positions, n => n.id, s => s.itemId, (n, s) => new { n, s }) 
        .OrderBy(x => x.s.Select(z => z.position)) 
        .ThenByDescending(x => x.n.articleDate) 
        .Select(x => x.n); 

mais je reçois la même erreur!

Si quelqu'un peut m'aider, ce serait très apprécié!

MISE À JOUR:
Alors après un certain jeu sur I ont réussi à le faire fonctionner.

ret = ret.GroupJoin(entity.Positions, n => n.id, s => s.itemId, (n, s) => new { n, s }) 
        .SelectMany(x => x.n.Positions.DefaultIfEmpty(), (n, s) => new { n, s }) 
        .OrderBy(x => x.s.position) 
        .ThenByDescending(x => x.n.n.articleDate) 
        .Select(x => x.n.n); 

Cependant, ceci n'est toujours pas complètement correct. Je n'ai aucun moyen d'utiliser seulement un positionid spécifique ou un articleType.

Si j'ai l'ID de nouvelles 1 et un ID de revue mais défini dans la table de positions, actuellement (je pense) la requête linq choisirait les deux?

Si j'essaie d'utiliser une clause where, c'est fondamentalement la même chose que la jointure interne. Ce que je besoin est d'essayer d'utiliser un cas dans la sélection comme je le ferais dans SQL droite:

CASE WHEN [position] IS NULL OR shuffleId != 1 THEN 9999 ELSE [position] END 

je dois repenser complètement comment faire. Ne supposez pas que quelqu'un a des suggestions de méthodes alternatives?

Répondre

2

Que diriez-vous:

var query = 
    from n in news 
    let p = n.Positions.Select(p=>p.Position).FirstOrDefault() ?? 9999 
    orderby p, n.ArticleDate 
    select n; 

Ps. ce qui précède suppose qu'il n'y a qu'une seule entrée de position pour chaque nouvelle ... semble juste bizarre si ce n'était pas le cas.


Solution publié par OP dans le commentaire ci-dessous:

ret = ret 
     .GroupJoin(tse.Positions, n => n.id, s => s.itemId, (n, s) => new { n, s }) 
     .SelectMany(x => x.s.DefaultIfEmpty(), (n, s) => new { n, s }) 
     .OrderBy(x => x.s.position == null || x.s.positionId != positionId ? 9999 : x.s.position) 
     .ThenByDescending(x => x.n.n.articleDate) 
     .Select(x => x.n.n); 
+0

Merci! Ce n'est toujours pas parfait mais je pense que je travaille votre réponse dans une réponse utilisable. –

+1

Juste pour référence voici comment je l'ai finalement résolu! Cela peut être un peu difficile à lire ici donc copier/coller est votre ami !: ret = ret.GroupJoin (tse.Positions, n => n.id, s => s.itemId, (n, s) => new {n, s}) .SelectMany (x => xsDefaultIfEmpty(), (n, s) => new {n, s}) .OrderBy (x => xsposition == null || xspositionId = positionId 9999: de xsposition) .ThenByDescending (x => xnnarticleDate) .Choisir (x => xnn)! –

1

Tout ce que je peux pour vous suggérons est l'utilisation d'une certaine méthode de procédure stockée - ajoutez à votre solution par la nouvelle classe LINQ to SQL , puis utilisez DataContext pour obtenir le résultat. Dans ce cas, vous n'utilisez pas la requête vers la base de données, ce qui est bon pour votre solution.

Seul le problème est que le type de résultat de cette procédure peut ne pas être compatible avec votre classe News Il se peut que vous deviez écrire du code pour transformer une représentation en une autre.

Si nécessaire, je peux fournir des illustrations pour ma façon de contourner le problème.