2010-11-11 8 views
1

J'ai une collection d'éléments où chaque élément a un champ "date" (le code est ci-dessous). J'essaie de combler les lacunes dans les dates dans la collection en utilisant LINQ. en particulier, je veux que la séquence résultante contienne tous les jours entre le premier et le dernier jour de la séquence originale. En plus de cela, ma requête LINQ résultante devrait être capable de gérer toutes les modifications de la séquence d'origine. c'est-à-dire que je ne peux pas calculer les dates minimales et maximales à l'avance.comment gérer les modifications de données source dans LINQ?

donc j'ai essayé le code ci-dessous mais il échoue quand il essaie de calculer Min et Max de la séquence. Je suis à la recherche d'une alternative "paresseux".

Merci pour toute aide konstantin


using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Linq; 

namespace consapp 
{ 
    class C 
    { 
     public DateTime date; 
     public int? value; 
    } 

    static class Program 
    { 
     static IEnumerable<C> dates(DateTime d0, DateTime d1) 
     { 
      for (var d = d0; d <= d1; d = d.AddDays(1)) 
      { 
       yield return new C { date = d }; 
      } 
     } 

     static void Main(string[] args) 
     { 
      var xs = new ObservableCollection<C>(); 

      var q = from d in dates(xs.Min(y => y.date), xs.Max(y => y.date)) 
        join x in xs on d.date equals x.date into js 
        from j in js.DefaultIfEmpty() 
        orderby d.date 
        select new { date = d.date, value = j != null ? j.value : null }; 

      xs.Add(new C { date = DateTime.Parse("11/10/11") }); 
      xs.Add(new C { date = DateTime.Parse("02/02/11") }); 
      xs.Add(new C { date = DateTime.Parse("11/24/11") }); 
      xs.Add(new C { date = DateTime.Parse("09/09/11") }); 
      xs.Add(new C { date = DateTime.Parse("11/10/11") }); 

      foreach (var x in q) 
      { 
       Console.WriteLine(x.date.ToShortDateString()); 
      } 
     } 
    } 
} 
+0

Bonjour konstantin, puisque Stackoverflow est une liste QnA éditée par la communauté, vous devriez éditer le titre de vos questions. Ou quel genre de réponse attendez-vous à la question «besoin d'aide avec linq»? Cordialement – Zeemee

+0

@Mulmoth: merci, nous espérons que la nouvelle ligne d'objet est plus spécifique – akonsu

Répondre

1

Je ne suis pas tout à fait positif, mais:

var q = from d in dates(xs.Min(y => y.date), xs.Max(y => y.date)) 

Je crois que la méthode "dates" sera appelée immédiatement, et le reste de la requête LINQ (y compris l'itérateur de dates() lui-même) sera construit autour du résultat de cette méthode. Vous devrez donc pré-remplir xs avec les données qui vous intéressent.

Ceci est dû au fait que LINQ fonctionne essentiellement en encapsulant des énumérats dans d'autres énumérables. Pour ce faire, il doit commencer par un énumérable. Pour ce faire, il doit appeler votre méthode order(), dont requiert en fournissant ses arguments immédiatement, afin qu'il puisse recevoir l'objet énumérable qu'il va encapsuler dans d'autres énumérables. Ainsi, les méthodes xs.Min et xs.Max seront appelées lorsque cette ligne de code sera atteinte, mais rien d'autre dans la requête ne sera réellement traité.

Une solution serait d'avoir votre méthode dates() reçoivent effectivement le ObservableCollection et appeler Min/Max lui-même. Comme cela se produira dans l'itérateur généré, l'exécution de ces appels sera différée comme prévu.

+0

passer l'ensemble de la collection aux dates() fonctionne. Merci. – akonsu

0

de mise en œuvre standard LINQ basé sur IEnumerable<T> ne peuvent pas gérer les sources de données qui changent telles que ObservableCollection. La raison pour laquelle votre exemple échoue est qu'il va essayer d'évaluer la source de données (et appeler les opérateurs dates et Min et Max) lorsque vous définissez la requête (mais la source de données ne contient aucune donnée à ce stade).

  • Une option consiste à utiliser une implémentation de LINQ alternative qui fonctionne avec ObservableCollection et peut mettre à jour automatiquement le résultat lorsque la source change. Pour autant que je sache, Bindable LINQ projet devrait être en mesure de le faire.

  • Une autre (simple) option est de transformer votre requête dans une méthode et appeler la méthode à plusieurs reprises (pour mettre à jour le résultat) lorsque vous savez que la source de données a changé. Il faudrait faire ObservableCollection un champ privé et la méthode serait tout simplement exécuter à l'aide des données actuellement stockées dans la collection:

    private ObservableCollection source; 
    void UpdateResults() { 
        var q = /* The query goes here */ 
        // Do something with the result of the query 
    } 
    
+0

merci pour la référence. J'ai juste essayé l'exemple de code dans cette page qu'ils disent ne montre rien à l'écran, et cela semble fonctionner. J'utilise. Net 4.0. il semble qu'ils ont maintenant cette capacité dans LINQ, non? – akonsu

Questions connexes