wake-up-neo.com

Erstellen Sie ein Tuple in einem Linq Select

Ich arbeite mit C # und .NET Framework 4.5.1, um Daten aus einer SQL Server-Datenbank mit Entity Framework 6.1.3 abzurufen.

Ich habe das:

codes = codesRepo.SearchFor(predicate)
      .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
      .ToList();

Und wenn ich es starte, erhalte ich folgende Nachricht:

In LINQ .__ werden nur parameterlose Konstruktoren und Initialisierer unterstützt. zu Entitäten.

Ich weiß nicht, wie ich das Tuple erstellen muss, da alle Beispiele, die ich gefunden habe, meistens wie dieses sind.

Ich habe das ausprobiert:

codes = codesRepo.SearchFor(predicate)
      .Select(c => Tuple.Create(c.Id, c.Flag))
      .ToList();

Und erhalte diesen Fehler:

LINQ to Entities erkennt die Methode nicht "System.Tuple" 2 [System.String, System.Byte] Erstellen Sie die Methode [String, Byte] (System.String, Byte) und diese Methode kann nicht in einen Speicherausdruck übersetzt werden.

Wo ist das Problem?

49
VansFannel

Während das answer by octavioccl funktioniert, ist es besser, das Abfrageergebnis zuerst in einen anonymen Typ zu projizieren und dann auf Aufzählungszeichen zu wechseln und es in Tuple zu konvertieren. Auf diese Weise ruft Ihre Abfrage nur die erforderlichen Felder aus der Datenbank ab. 

codes = codesRepo.SearchFor(predicate)
    .Select(c => new { c.Id, c.Flag })
    .AsEnumerable()
    .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
    .ToList();
68
Ivan Stoev

Versuche dies:

codes = codesRepo.SearchFor(predicate)
  .Select(c => Tuple.Create(c.Id, c.Flag))
  .ToList();

Informiert wurde, dass dies in LINQ nicht zu Entitäten akzeptiert wird.

Eine andere Option wäre, das Ergebnis vor der Auswahl in den Speicher zu ziehen. Wenn Sie dies tun, würde ich empfehlen, die gesamte Filterung vor .AsEnumerable () durchzuführen, da dies bedeutet, dass Sie nur die gewünschten Ergebnisse zurückziehen und nicht die gesamte Tabelle zurückziehen und dann filtern.

codes = codesRepo.SearchFor(predicate).AsEnumerable()
  .Select(c => Tuple.Create(c.Id, c.Flag))
  .ToList();

auch Tuple.Create (c.Id, c.Flag) könnte in new Tuple (c.Id, c.Flag) geändert werden, wenn Sie den Code in den Tupeltypen etwas expliziter machen möchten 

9
Dhunt

In linq to entity können Sie auf einen anonymen Typ oder auf einen DTO projizieren. Um dieses Problem zu vermeiden, können Sie die Erweiterungsmethode AsEnumerable verwenden:

codes = codesRepo.SearchFor(predicate).AsEnumerable().
      .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
      .ToList();

Mit dieser Methode können Sie mit Linq to Object statt mit Linq to Entities arbeiten. Nach dem Aufruf können Sie das Ergebnis Ihrer Abfrage in das gewünschte Ergebnis projizieren. Der Vorteil der Verwendung von AsEnumerableToList ist, dass AsEnumerable die Abfrage nicht ausführt, die verzögerte Ausführung bleibt erhalten. Es ist eine gute Idee, Ihre Daten immer zuerst zu filtern, bevor Sie eine dieser Methoden aufrufen.

8
octavioccl

Nur eine aktualisierte Antwort für C # 7, jetzt können Sie zum Erstellen von ValueTuples eine einfachere Syntax verwenden.

codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag })
.AsEnumerable()
.Select(c => (c.Id, c.Flag))
.ToList();

Sie können jetzt sogar die Eigenschaften des Tuples benennen:

codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag })
.AsEnumerable()
.Select(c => (Id: c.Id, Flag: c.Flag))
.ToList();

Anstatt es als Item1 oder Item2 zu verwenden, können Sie als ID oder Flag darauf zugreifen.

7
Rafael Merlin

Ich habe die Antwort gefunden:

codes = codesRepo.SearchFor(predicate)
      .ToList()
      .Select(c => Tuple.Create(c.Id, c.Flag))
      .ToList();
3
VansFannel

Verwenden Sie diese Methode und verwenden Sie asynchron.

var codes = await codesRepo.SearchFor(predicate)
                    .Select(s => new
                    {
                        Id = s.Id,
                        Flag = s.Flag
                    }).FirstOrDefaultAsync();

                var return_Value = new Tuple<string, byte>(codes.Id, codes.Flag);
1
MohammadSoori

Nur meine zwei Cent: Das hat mich ein paar Mal mit den Typnamen erwischt:

Einige wenige Beispiele:

    private Tuple<string, byte> v1()
    {
        return new Tuple<string, byte>("", 1);
    }

    private (string, int) v2()
    {
        return ("", 1);
    }

    private (string Id, byte Flag) v3()
    {
        return ("", 1);
    }

Grüße.

0
IbrarMumtaz