2016-05-25 3 views
5

Gegeben:Use-Liste <Tuple <int, int>>, um Daten in Linq

List<int> myList; 

Wenn ich wollte Daten zurückzukehren, wo die Datensatz-ID in dieser Liste enthalten war, würde ich einfach tun:

var q = db.Table.Where(c=> myList.Contains(c.ID)); 

Jedoch:

List<Tuple<int, int>> myList; 

Wie würde ich eine Linq-Abfrage schreiben, um Datensätze zurückzugeben, wo beide Bedingungen erfüllt sind? Mit einem Datenpunkt würde ich schreiben:

var q = db.Table.Where(c=> 
      c.ID == myList.Item1 
      && c.AnotherValue == myList.Item2); 

Wie würde ich die obige Aussage konvertieren auf einem List<Tuple<int, int>> zu arbeiten?

Antwort

6

Eine Tuple ist eine Struktur, die nicht von Ihrem Linq Provider in sql übersetzt werden kann. Eine Lösung könnte eine Umstellung auf Linq to Objects

var q = db.Table.AsEnumerable() 
       .Where(c=> myList.Any(tuple => c.ID == tuple.Item1 && 
              c.AnotherValue == tuple.Item2)); 

Aber das Schlimme an dieser Lösung werden ist, dass Sie alle laden, um die Zeilen aus dieser Tabelle im Speicher zu filtern gehen.

könnte andere Lösung Linqkit Verwendung werden:

var predicate = PredicateBuilder.False<Table>(); 

foreach (string t in myList) 
{ 
    predicate = predicate.Or(c =>c.ID == t.Item1 && c.AnotherValue == t.Item2)); 
} 

db.Table.AsExpandable().Where(predicate); 

Sie weitere Informationen über diese letzte Lösung in diesem link

+0

Ja, aber für mehrere Werte? Wenn ich eine Liste von 100 Paaren habe, möchte ich keine Abfrage für jede einzelne ausführen. –

+0

Danke, PredicateBuilder scheint hier eine gute Option zu sein! –

+0

Gern geschehen;) – octavioccl

1
var q = db.Table.AsEnumerable().Where(c => myList.Any(tuple => c.ID == tuple.Item1 && 
               c.AnotherValue == tuple.Item2)); 

Mit Any können Sie überprüfen, ob es mindestens ein Element in myList die Spiele Ihr Zustand ist. Wie @octaviocci darauf hinwies, ist dies nicht in SQL übersetzbar. Sie müssten also vorher AsEnumerable() aufrufen und die Filterung lokal durchführen, was möglicherweise nicht das ist, was Sie wünschen, wenn es viele irrelevante Datensätze gibt.

0

Hier einige Beispielcode, der einen Ansatz zeigt finden:

DataTable dt = new DataTable("demo"); 
// hydrate your table here... 

List<Tuple<int, int>> matches = new List<Tuple<int, int>>(); 

Func<List<Tuple<int,int>>, DataRow, bool> RowMatches = (items, row) => { 

     var rowValue1 = (int)row["Id"]; 
     var rowValue2 = (int)row["SomeOtherValue"]; 

     return items.Any(item => item.Item1 == rowValue1 && item.Item2 == rowValue2); 
    }; 

var results = dt.Rows.Cast<DataRow>().Where(r => RowMatches(matches, r)); 
Console.WriteLine(results.Any()); 
0

Siehe Code unten:

List<Tuple<int, int>> myList; 

var set = new HashSet(myList); 

var q = db.Table.AsEnumerable().Where(c=> set.Contains(new Tuple(c.ID, c.AnotherValue))); 

Beachten Sie, dass der Hash-Satz verwendet wird, um die Ausführung der Klausel Where für große myList Leistung zu optimieren.

+0

Wird dies nicht einfach nur mit jedem Element von Set1 mit jedem Element von Set2 übereinstimmen? –

0

Da Tuple nicht in Linq to Entities verwendet werden, können Sie so etwas wie dies versuchen:

List<int> items1 = myList.Select(t => t.Item1).ToList(); 
List<int> items2 = myList.Select(t => t.Item2).ToList(); 

var q = db.Table.GroupBy(m => { m.ID, m.AnotherValue }) 
       .Where(g => items1.Contains(g.Key.ID) && 
          items2.Contains(g.Key.AnotherValue)) 
       .SelectMany(g => g); 
Verwandte Themen