2016-04-26 5 views
1

Auf der Grundlage dieser Beiträge:Was wäre der beste Weg, ein IReliableDictionary zu suchen?

Convert IReliableDictionary to IList

What is the most optimal method of querying a reliable dictionary collection

Ich sollte Linq in der Lage zu verwenden, um eine IReliableDictionary abzufragen, aber es scheint, dass diese Schnittstelle nicht mehr implementiert IEnumerable und die Linq-Erweiterungen nicht sind verfügbar. Zumindest in Version 5.0.0.0 der Microsoft.ServiceFabric.Data.Interfaces-Assembly.

Wenn das stimmt, was wäre der beste Weg, ein IReliableDictionary zu suchen?

Antwort

10

Ja, wir haben IEnumerable in der GA-Version von Reliable Collections entfernt. Wie Allan T erwähnt, sind zuverlässige Sammlungen nicht wirklich dieselben wie normale .NET-Sammlungen, obwohl sie die gleichen grundlegenden Datenstrukturen darstellen. Einer der großen Unterschiede, den Sie wahrscheinlich bemerkt haben, ist, dass alle Operationen asynchron sind, weil Semantik und I/O für die Replikation und das Lesen von Festplatten gesperrt sind. Es ist der letzte Teil, der die Entscheidungen zur Entfernung von IEnumerable vorangetrieben hat, weil es streng synchron ist und wir nicht sind. Stattdessen verwenden wir jetzt IAsyncEnumerable, das die vollständigen LINQ-Erweiterungsmethoden noch nicht unterstützt.

Wir arbeiten an asynchronen LINQ-Erweiterungsmethoden, aber in der Zwischenzeit gibt es mehrere Möglichkeiten, mit IAsyncEnumerable zu arbeiten.

Eli Arbel has async extension methods on Gist, die eine Brücke zu System.Interactive.Async und auch asynchrone Implementierungen von Select, SelectMany und Where bieten.

Oder Sie können wrap IAsyncEnumerable in a regular IEnumerable, die einfach die asynchronen Aufrufe mit synchronen Methoden umschließt, und das wird Ihnen die vollständige Reihe von Methoden LINQ-Erweiterungen wieder. Dann können Sie die Erweiterungsmethode in einer regulären LINQ-Abfrage verwenden:

 using (ITransaction tx = this.StateManager.CreateTransaction()) 
     { 
      var x = from item in (await clusterDictionary.CreateEnumerableAsync(tx)).ToEnumerable() 
        where item.Value.Status == ClusterStatus.Ready 
        orderby item.Value.CreatedOn descending 
        select new ClusterView(
         item.Key, 
         item.Value.AppCount, 
         item.Value.ServiceCount, 
         item.Value.Users.Count(), 
         this.config.MaximumUsersPerCluster, 
         this.config.MaximumClusterUptime - (DateTimeOffset.UtcNow - item.Value.CreatedOn.ToUniversalTime())); 

     } 
+0

Nur eine kleine Anmerkung - die Erweiterungen bieten eine Brücke zur Ix-Async NuGet-Bibliothek, die eine ** vollständige ** asynchrone LINQ-Implementierung enthält. Der Basisteil bezieht sich auf die asynchronen Versionen der Operatoren, von denen ich nur 'SelectAsync',' SelectManyAsync' und 'WhereAsync' implementiert habe. –

+0

(Diese asynchronen Operatoren unterstützen Szenarien wie Querabfragen anderer Sammlungen) –

+0

Danke für die Klarstellung , Eli, ich habe meine Antwort aktualisiert. –

0

Soweit ich weiß, die Service Fabric zuverlässige Wörterbücher können wie ein normales .NET-Wörterbuch aussehen, aber sie sind nicht wirklich gleich. Daher werden einige Methoden möglicherweise nicht im zuverlässigen SF-Wörterbuch oder in der Warteschlange unterstützt.

+0

Noch im Oktober 2015 hat ein Senior Program Manager von MS geschrieben, dass LINQ auf dieser Sammlung verfügbar ist (zweiter Link oben). Es scheint, dass die Möglichkeit, LINQ-Erweiterungen zu verwenden, vor GA of Service Fabric entfernt wurde. – RWilkinson

2

Ich weiß nicht, ob es der „beste“ Weg ist, aber ich habe mit den folgenden

public static async Task<IList<KeyValuePair<Guid, T>>> QueryReliableDictionary<T>(IReliableStateManager stateManager, string collectionName, Func<T, bool> filter) 
{ 
    var result = new List<KeyValuePair<Guid, T>>(); 

    IReliableDictionary<Guid, T> reliableDictionary = 
     await stateManager.GetOrAddAsync<IReliableDictionary<Guid, T>>(collectionName); 

    using (ITransaction tx = stateManager.CreateTransaction()) 
    { 
     IAsyncEnumerable<KeyValuePair<Guid, T>> asyncEnumerable = await reliableDictionary.CreateEnumerableAsync(tx); 
     using (IAsyncEnumerator<KeyValuePair<Guid, T>> asyncEnumerator = asyncEnumerable.GetAsyncEnumerator()) 
     { 
      while (await asyncEnumerator.MoveNextAsync(CancellationToken.None)) 
      { 
       if (filter(asyncEnumerator.Current.Value)) 
        result.Add(asyncEnumerator.Current); 
      } 
     } 
    } 
    return result; 
} 

Sie die Verwendung Methode, indem Sie den StateManager, den Namen der Sammlung, die Sie abfragen möchten, und eine Lambda-Funktion mit Ihrer Abfragelogik übergeben. Zum Beispiel:

+0

Ich sollte erwähnen, ich habe Guid für meine Wörterbuchschlüssel verwendet. Wenn Sie einen anderen Typ verwenden müssen, müssen Sie den Code entsprechend anpassen. –

+0

Das ist fast identisch mit dem, was ich getan habe, danke. – RWilkinson