2017-02-25 3 views
0

die folgenden Klassen vor:Überprüfen Sie, ob eine Sammlung aller Werte aus einer anderen Sammlung mit verzögerter Ausführung enthält

public class Recipe 
{ 
    public string Id { get; set; } 
    public ICollection<RecipeFacet> RecipeFacets { get; set; } 
} 

public class RecipeFacet 
{ 
    public string Id { get; set; } 
    public Facet Facet { get; set; } 
    public string RecipeId { get; set; } 
} 

public class Facet 
{ 
    public string Name { get; set; } 
} 

Ich brauche eine vorhandene Abfrage zu verbessern. Ich dachte daran, Linqs verzögerte Ausführung zu verwenden. Wie würde ich eine Linq-Abfrage schreiben, die nur Recipes zurückgibt, die ALL enthält Facets ich in einer Liste von Tuples angeben?

Dies ist der ursprüngliche Code, der Recipes und seine Facets durchläuft. Es funktioniert, aber es ist langsam, wenn meine erste results Abfrage hat viele Recipes.

IQueryable<Recipe> result; //assume we have data here 

string query = "Cuisine:American+Recipe-Type:dinners"; 
IEnumerable<Tuple<string, string>> taxFacets = query 
      .Split(' ') 
      .Select(tf => tf.Split(':')) 
      .Select(tf => new Tuple<string, string>(tf[0], tf[1])) 
      .Distinct(); 

var recipeFacetCollection = result.Select(r => r.RecipeFacets).ToList(); 
var matchedRecipesIds = new List<string>(); 

var recIds = result.Select(r => r.Id).ToList(); 

// initially, include all recipes 
matchedRecipesIds.AddRange(recIds); 

// loop through each recipe's facet collection 
foreach (var col in recipeFacetCollection) 
{ 
    // loop through the tax facets from the query 
    foreach (var tf in taxFacets) 
    { 
     var exists = col.Any(f => f.Facet.Name.Equals(tf.Item2, StringComparison.OrdinalIgnoreCase)); 
     // remove any recipe that is missing a facet 
     if (!exists) 
     { 
      matchedRecipesIds.Remove(col.First().RecipeId); 
     } 
    } 
} 

result = result.Where(r => matchedRecipesIds.Contains(r.Id)); 

Wie kann ich eine nette Linq-Abfrage mit verzögerter Ausführung haben?

UPDATE ::

Turning meine Tuple in eine Liste ermöglicht es mir, dies zu tun. Aber diese Abfrage gibt keine meiner Datensätze zurück.

Dies ist meine Kriterien:

Recipes, die eine Sammlung von RecipeFacts haben, die Facets enthält, der Name = "American" AND Name = "Abendessen" haben.

var listFacets = new List<string>() 
{ 
    "American", 
    "dinners" 
}; 

result = result 
     .Where(r => r.RecipeFacets 
     .All(f => !listFacets.Any(t => t.Equals(f.Facet.Name, StringComparison.OrdinalIgnoreCase)))); 

Antwort

0

bekam ich das von @ Rimp Hilfe.

WHERE - Filter
ALL - verlangen, dass alle Werte von listFacets
ANY - ANY in der Facets ist.

0

Ich bin nicht ganz dazu führen, dass Ihr Code-Block ist ziemlich lang, aber hier ist das, was ich mit oben kommen kann

result = result.Where(r => r.RecipeFacets.All(f => taxFacets.Any(t => t.Item1.Equals(f.Facet.Name)))); 

Lassen Sie mich wissen, ob es oder nicht

hilft
+0

Danke für den Vorschlag. Aber ich erhalte diesen Fehler: "Es konnte kein konstanter Wert vom Typ 'System.Tuple' erstellt werden. Nur primitive Typen oder Aufzählungstypen werden in diesem Kontext unterstützt. – duyn9uyen

+0

Können Sie Ihren Code posten?Welche Codezeile erhalten Sie Fehler? –

+0

Ich verwende Ihren Vorschlag. Doing eine result.toList() warf diesen Fehler. – duyn9uyen

0

den Ausruf entfernen aus der Klausel in der Überprüfung der ListFacets-Auflistung.

result = result.Where(r => r.RecipeFacets.All(f => listFacets.Any(t => t.Equals(f.Facet.Name, StringComparison 
1

Ihre Abfragelogik wählt alle Rezepte aus, deren Facetten in listFacets nicht vorhanden sind. @ Hung Logik ist näher, sondern wählt Rezepte, die alle ihrer Facetten in listFacets haben

Ich denke, dass Sie alle Rezepte auswählen möchten, die alle listFacets enthalten.

das Beispiel Vereinfachen Listen von Zeichenketten zu verwenden:

 var listFacets = new[] { "a", "d" }; 
     var recipes = new[] { new[] { "a" }, 
           new[] { "a", "d" }, 
           new[] { "a", "d", "e" }, 
           new[] { "x" } 
     }; 

     // correct query, returns 2 results ad and ade 
     var result = recipes.Where(r => listFacets.All(f => r.Any(rf => rf == f))); 
     // original incorrect query, returns x 
     var result2 = recipes.Where(r => r.All(f => !listFacets.Any(rf => rf == f))); 
+0

Da Sie die Objekte vereinfacht haben, ist die Abfrage nicht identisch. Aber danke für den Vorschlag. Ich denke, @hung ist sehr nahe. – duyn9uyen

Verwandte Themen