2017-02-10 3 views
1

Ich benutze .NET 4.5 in C#, und ich habe zwei Sammlungen von verschiedenen Klassen, die ich vergleichen möchte. Sie haben einige Spalten mit ähnlichen Namen, aber sie implementieren keine gemeinsame Schnittstelle (und können aus Gründen des Codierungsstandards nicht).linq - Wie findet man heraus, ob die Schlüsselspalten einer Sammlung eine Untermenge einer anderen Sammlung sind?

Die erste Klasse sieht wie folgt aus:

class Foo 
{ 
    string Key1 {get; set;} 
    string Key2 {get; set;} 
    string NotKey {get; set;} 
    string AlsoNotKey {get; set;} 
} 

Während die zweite sieht wie folgt aus:

class Bar 
{ 
    string Key1 {get; set;} 
    string Key2 {get; set;} 
} 

Was ich tun möchte, ist eine Sammlung von Foo in eine Methode übergeben und das Rück true wenn jedes einzelne Paar von Key1 und Key2 darin eine Übereinstimmung in einer Sammlung von Bar hat, die von einer Datenbank (über EF) abgerufen wird, aber ich kann nicht herausfinden, wie man das macht.

Meine erste Idee etwas so aussah ...

//IEnumerable<Foo> foos 
//DbSet<Bar> bars 
foos.All(foo => foo.Key1 == bars.Key1 && foo.Key2 == bars.Key2) 

... aber es funktioniert nicht, weil bars eine Sammlung zu, und ich kann nur Contains() nicht um jede Spalte verwenden, weil dann Es wird nicht beide Spalten als ein Paar vergleichen.

In SQL, kann ich etwas tun, wie

SELECT COUNT(*) 
FROM foos 
JOIN bars 
ON foos.key1 = bars.key1 
AND foos.key2 = bars.key2 

und vergleichen Sie es mit der Anzahl der Datensätze in foos von selbst, aber wie kann ich das LINQ übersetzen?

Bearbeiten: Gefunden diese verwandte Frage. How to use linq `Except` with multiple properties with different class?

Könnte etwas so versuchen, es sei denn, es gibt einen besseren Weg.

foos.All(f => bars.Any(b => f.Key1 == b.Key1 && f.Key2 == b.Key2)) 
+0

Haben Sie versucht, [LINQ verbinden] (https://msdn.microsoft.com/en-us/library/bb534675.aspx)? Es könnte genau das tun, wonach Sie suchen. –

+0

Sie sollten eine Join-Abfrage in Linq zu Entitäten schreiben. https://msdn.microsoft.com/en-us/library/bb311040.aspx https://msdn.microsoft.com/en-us/library/bb896266(v=vs.110).aspx – DaniDev

Antwort

1

Versuchen Sie folgendes:

var x = (from f in foos 
     join b in bars on new { f.Key1, f.Key2 } equals new { b.Key1, b.Key2 } 
     select f).Count(); 

Ich weiß, es ist eine lange Form, aber dies ist der Fall, in dem es mehr beschreibend als die kurze Form ist.

Die große Annahme ist natürlich, dass Ihre Schlüssel nicht duplizieren. Wenn sie das tun werden Sie falsche Einzelteil

1

Versuchen Sie, diese

bool IsFooASubsetOfBar(List<Foo> foos, List<Bar> bars) 
{ 
    if (foos == null || bars == null) 
     return false; 

    return foos.All(foo => bars.Any(bar => bar.Key1 == foo.Key1 && bar.Key2 == foo.Key2)); 
} 

Verbrauch zählen erhalten:

List<Bar> bars = new List<Bar>() 
      { 
       new Bar() { Key1 = "1", Key2 = "1" }, 
       new Bar() { Key1 = "2", Key2 = "2" }, 
       new Bar() { Key1 = "3", Key2 = "3" } 
      }; 

List<Foo> foos = new List<Foo>() 
      { 
       new Foo() { Key1 = "2", Key2 = "2" }, 
       new Foo() { Key1 = "3", Key2 = "3" } 
      }; 

bool b = IsFooASubsetOfBar(foos); 
1

können Sie einen join verwenden, aber ich würde eine count nicht tun, denn das würde zwingen Sie berücksichtigen doppelte Schlüsseltupel. Ich würde verwenden eine left join statt:

public bool Matches(IEnumerable<Foo> foos, DbSet<Bar> bars) 
{ 
     return (from f in foos 
       join b in bars on new {f.Key1, f.Key2} equals new {b.Key1, b.Key2} into fjb 
       from match in fjb.DefaultIfEmpty() 
       select match != null 
       ).All(isMatch => isMatch);  
} 
Verwandte Themen