7
votes

Mettre à jour l'objet dans Ienumerable <> Ne pas mettre à jour?

J'ai un iénumérable d'un type de POCO contenant environ 80 000 rangées et une table de base de données (L2E / EF4) contenant un sous-ensemble de lignes dans lesquelles il y avait une "erreur / une différence" (environ 5000 lignes, mais souvent répétée pour donner environ 150 entrées distinctes)

Le code suivant obtient le VSacode distinct "En erreur", puis tente de mettre à jour le jeu de résultats complet, mettez à jour les lignes qui correspondent à ... mais cela ne fonctionne pas! P>

foreach (var code in vsaCodes)
    {
        results.Where(r => r.VSACode == code).Select(r => { r.Difference = true; return r; }).ToList();
    }


0 commentaires

3 Réponses :


14
votes

En supposant que résultats est juste une requête (vous ne l'avez pas montrée), il sera évalué chaque fois que vous iTerez-le dessus. Si cette requête crée de nouveaux objets à chaque fois, vous ne vous ne voit pas les mises à jour. Si cela renvoie des références aux mêmes objets, vous le feriez.

Si vous modifiez les résultats pour être un résultat de requête matérialisé - par exemple En ajoutant Tolist () à la fin - Ensuite, itération sur résultats ne sera pas émettre une nouvelle requête, et vous verrez vos modifications.


6 commentaires

Mon compréhension (clairement pas parfaite) était d'éviter d'utiliser Tolist () à moins que vous n'en aviez vraiment besoin ... Je suppose que c'est une situation "vraiment besoin"? Quick Q? Est-il préférable d'appeler tolist () tôt dans ma chaîne de déclarations / requêtes pour matérialiser la liste? Si je ne le fais pas, cela interrogera-t-il la DB chaque fois qu'il est utilisé?


@Bluechippy: Vous devez généralement utiliser TOLIST TOLIST SA TARD que vous pouvez, de sorte que la majeure partie de la requête (en particulier des parties qui filtrent la sortie) s'exécute dans la base de données.


Merci Jon, suppose que j'avais laissé cette toliste () un peu d'essais (););


@Jonskeet: légèrement tweak, si vous avez une requête sur une source "matérialisée" sous-jacente, vous pouvez mettre à jour les objets source via la requête résultante. La requête sera réévaluée à chaque fois et si votre requête contient un filtre, vous pouvez filtrer des éléments en fonction de la mise à jour, mais la source restera mise à jour. Si votre requête contient une projection (SELECT ()) dans une classe (par opposition à un type anonyme), cela va rompre le lien vers les objets source.


@andler: J'ai bien peur que ce ne soit pas vraiment clair pour moi ce que tu veux dire. Peut-être devriez-vous ajouter votre propre réponse?


@Jonskeet, posté. Total Edge Case et je n'ai vraiment pas répondu à la question de l'OP mais comme vous l'avez souligné, c'est un peu vague.



2
votes

J'ai eu le même genre d'erreur il y a quelque temps. Le problème est que les requêtes LINQ sont souvent différées et non exécutées lorsqu'elles apparaissent que vous les appelez.

Citation de " Query intégré de langage Pro Linq en C # 2010 ":

"Notez que même si nous avons appelé la requête seulement une fois, les résultats de L'énumération est différente pour chacune des énumérations. C'est des preuves supplémentaires que la requête est différée. Si ce n'était pas, le Les résultats des deux énumérations seraient les mêmes. Cela pourrait être un bénéfice ou préjudice. Si vous ne voulez pas que cela se produise, utilisez l'un des les opérateurs de conversion qui ne renvoient pas un iéorérable afin que La requête n'est pas différée, telle que Toarray, Tolist, Todicty, ou Tolookup, pour créer une structure de données différente avec des résultats mis en cache cela ne changera pas si la source de données change. "

Ici, vous avez une bonne explication avec des exemples de celui-ci:

http: //blogs.msdn. COM / B / CHARLIE / ARCHIVE / 2007/12/09 / DIFFERED-Execution.aspx

considère


0 commentaires

0
votes

Mots d'analyse assez étroitement sur la réponse de @ Jonskeet ...

Si votre requête est simplement un filtre et que les objets source sous-jacents sont mis à jour, la requête sera réévaluée et peut exclure ces objets en fonction de la condition de filtrage auquel cas Les résultats de vos requêtes vont changer sur les énumérations ultérieures, mais les objets sous-jacents auront toujours été mis à jour.

La clé est un manque de projection à un nouveau type dans la mise à jour et la persistance des objets modifiés.

tolist () est la solution habituelle à ce problème et il résoudra le problème s'il existe une projection à un nouveau type, mais les choses deviennent nuageux dans l'événement de vos filtres de requête, mais ne projet pas. Les mises à jour de la requête affectent toujours les objets source d'origine donnés que tout est référençant le même objet.

Encore une fois, des mots d'analyse mais ces cas de bord peuvent vous trébucher. < Pré> xxx


0 commentaires