569 Stimmen

Join/Where mit LINQ und Lambda

Ich habe Probleme mit einer Abfrage in LINQ und Lambda geschrieben. Bisher bekomme ich eine Menge von Fehlern hier ist mein Code:

int id = 1;
var query = database.Posts.Join(database.Post_Metas,
                                post => database.Posts.Where(x => x.ID == id),
                                meta => database.Post_Metas.Where(x => x.Post_ID == id),
                                (post, meta) => new { Post = post, Meta = meta });

Ich bin neu bei der Verwendung von LINQ, daher bin ich nicht sicher, ob diese Abfrage korrekt ist.

14 Stimmen

Was wollen Sie erreichen?

4 Stimmen

Was soll die Abfrage in einem Satz bewirken?

6 Stimmen

Ihre wichtigsten Selektoren sind Weg zu kompliziert. Wenn Sie nach der ID auswählen möchten, reicht x=>x.ID aus.

1303voto

Daniel Schaffer Punkte 54690

Wenn Sie mit der SQL-Syntax vertraut sind, finde ich, dass die LINQ-Abfragesyntax viel klarer und natürlicher ist und es einfacher macht, Fehler zu erkennen:

var id = 1;
var query =
   from post in database.Posts
   join meta in database.Post_Metas on post.ID equals meta.Post_ID
   where post.ID == id
   select new { Post = post, Meta = meta };

Wenn Sie wirklich auf die Verwendung von Lambdas stecken aber, Ihre Syntax ist ziemlich viel aus. Hier ist die gleiche Abfrage, unter Verwendung der LINQ-Erweiterungsmethoden:

var id = 1;
var query = database.Posts    // your starting point - table in the "from" statement
   .Join(database.Post_Metas, // the source table of the inner join
      post => post.ID,        // Select the primary key (the first part of the "on" clause in an sql "join" statement)
      meta => meta.Post_ID,   // Select the foreign key (the second part of the "on" clause)
      (post, meta) => new { Post = post, Meta = meta }) // selection
   .Where(postAndMeta => postAndMeta.Post.ID == id);    // where statement

98voto

Damian Powell Punkte 8397

Man kann das auf zwei Arten angehen. Verwendung von LINQPad (von unschätzbarem Wert, wenn Sie neu in LINQ sind) und eine Dummy-Datenbank, habe ich die folgenden Abfragen erstellt:

Posts.Join(
    Post_metas,
    post => post.Post_id,
    meta => meta.Post_id,
    (post, meta) => new { Post = post, Meta = meta }
)

oder

from p in Posts
join pm in Post_metas on p.Post_id equals pm.Post_id
select new { Post = p, Meta = pm }

In diesem speziellen Fall halte ich die LINQ-Syntax für sauberer (ich wechsle zwischen den beiden, je nachdem, was am einfachsten zu lesen ist).

Ich möchte jedoch darauf hinweisen, dass Sie, wenn Sie geeignete Fremdschlüssel in Ihrer Datenbank haben (zwischen post und post_meta), wahrscheinlich keine explizite Verknüpfung benötigen, es sei denn, Sie versuchen, eine große Anzahl von Datensätzen zu laden. Ihr Beispiel scheint darauf hinzudeuten, dass Sie versuchen, einen einzelnen Beitrag und seine Metadaten zu laden. Angenommen, es gibt viele post_meta-Datensätze für jeden Beitrag, dann könnten Sie Folgendes tun:

var post = Posts.Single(p => p.ID == 1);
var metas = post.Post_metas.ToList();

Wenn Sie das n+1-Problem vermeiden möchten, können Sie LINQ to SQL explizit anweisen, alle zugehörigen Elemente in einem Durchgang zu laden (obwohl dies ein Thema für Fortgeschrittene sein könnte, wenn Sie mit L2S besser vertraut sind). Im folgenden Beispiel heißt es: "Wenn Sie einen Beitrag laden, laden Sie auch alle Datensätze, die über den Fremdschlüssel, der durch die Eigenschaft 'Post_metas' repräsentiert wird, mit ihm verbunden sind":

var dataLoadOptions = new DataLoadOptions();
dataLoadOptions.LoadWith<Post>(p => p.Post_metas);

var dataContext = new MyDataContext();
dataContext.LoadOptions = dataLoadOptions;

var post = Posts.Single(p => p.ID == 1); // Post_metas loaded automagically

Es ist möglich, viele LoadWith Anrufe bei einem einzigen Satz von DataLoadOptions für denselben Typ oder für viele verschiedene Typen. Wenn Sie dies jedoch häufig tun, sollten Sie eine Zwischenspeicherung in Betracht ziehen.

76voto

Talspaugh27 Punkte 893

Daniel hat eine gute Erklärung der Syntaxbeziehungen, aber ich habe dieses Dokument für mein Team zusammengestellt, um es für sie ein wenig einfacher zu machen. Hoffentlich hilft das jemandem enter image description here

0 Stimmen

@Talspaugh27 Warum wird dann in der SQL-Abfrage eine Verknüpfung mit gStatus auf g.id vorgenommen? Ist das ein Fehler oder beabsichtigt?

0 Stimmen

@Drammy in einer Sql-Tabelle muss jede Spalte einen Namen haben. Da es sich um eine 1-Spalten-Tabelle handelt, in der nur die IDs gespeichert werden sollen, habe ich einfach eine Spalte mit dem Namen id verwendet, die List<int> hat dieses Problem nicht. Wenn ich es so eingerichtet hätte public class IdHolder{ int id } dann dieses Objekt in gStatus verwendet List<IdHolder> gStatus = new List<IdHolder>(); gStatus.add(new IdHolder(){id = 7}); gStatus.add(new IdHolder(){id = 8}); dann hätte es die Linq wie folgt geändert t =>t.value.TaskStatusId, g=>g.id Ist diese Änderung sinnvoll?

0 Stimmen

@Talspaugh27 Ja, sicher, ich schätze, ich habe nur gefragt, ob die Syntax im Bild kompiliert werden kann (aber ich könnte es auch einfach selbst testen!). Danke

40voto

Mark Byers Punkte 761508

Ihre Schlüsselwahlen sind falsch. Sie sollten ein Objekt vom Typ der fraglichen Tabelle nehmen und den Schlüssel zurückgeben, der in der Verknüpfung verwendet werden soll. Ich denke, Sie meinen dies:

var query = database.Posts.Join(database.Post_Metas,
                                post => post.ID,
                                meta => meta.Post_ID,
                                (post, meta) => new { Post = post, Meta = meta });

Sie können die Where-Klausel nachträglich anwenden, nicht als Teil des Schlüsselselektors.

9voto

Abfragesyntax für LINQ Join

var productOrderQuery = from product in Product.Setup()//outer sequence
                        join order in OrderDetails.Setup()//inner sequence
                        on product.Id equals order.ProductId //key selector
                        select new//result selector
                        {
                            OrderId = order.Id,
                            ProductId = product.Id,
                            PurchaseDate = order.PurchaseDate,
                            ProductName = product.Name,
                            ProductPrice = product.Price
                        };

Methodensyntax für LINQ Join

var productOrderMethod = Product.Setup().//outer sequence
    Join(OrderDetails.Setup(), //inner sequence
    product => product.Id//key selector
    ,order=> order.ProductId //key selector
    ,(product,order)=> //projection result
        new
        {
            OrderId = order.Id,
            ProductId = product.Id,
            PurchaseDate = order.PurchaseDate,
            ProductName = product.Name,
            ProductPrice = product.Price
        }
    );

Product.cs als Referenz

class Product
{
    public int Id { get; set; }
    public string Name { get; set; }

    public decimal Price { get; set; }
    public static IEnumerable<Product> Setup()
    {
        return new List<Product>()
        {
            new Product(){Id=1, Name="Bike", Price=30.33M },
            new Product(){Id=2, Name="Car", Price=50.33M },
            new Product(){Id=3, Name="Bus", Price=60.33M }
        };
    }
}

OrderDetails.cs Klasse als Referenz

class OrderDetails
{
    public int Id { get; set; }
    public virtual int ProductId { get; set; }

    public DateTime PurchaseDate { get; set; }
    public static IEnumerable<OrderDetails> Setup()
    {
        return new List<OrderDetails>()
        {
            new OrderDetails(){Id=1, ProductId=1, PurchaseDate= DateTime.Now },
            new OrderDetails(){Id=2, ProductId=1, PurchaseDate=DateTime.Now.AddDays(-1) },
            new OrderDetails(){Id=3, ProductId=2, PurchaseDate=DateTime.Now.AddDays(-2) }
        };
    }

}

0 Stimmen

Können Sie eine Antwort mit wo Bedingung in Methode Syntax für LINQ Join bereitstellen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X