2008-08-21 7 views
20

Ich vermisse etwas über LINQ. Für mich sieht es so aus, als würde ich einige der SQL-Elemente, die ich am wenigsten mag, in die C# -Sprache übernehmen und für andere Dinge verwenden.Fehle ich etwas über LINQ?

Ich meine, ich könnte den Vorteil der Verwendung von SQL-ähnlichen Anweisungen auf andere Dinge als Datenbanken sehen. Aber wenn ich SQL schreiben wollte, warum schreibe ich nicht einfach SQL und behalte es nicht in C#? Was fehlt mir hier?

Antwort

39

LINQ ist nicht über SQL. Bei LINQ geht es darum, funktionale Programmierparadigmen auf Objekte anzuwenden.

LINQ to SQL ist ein ORM, das auf der LINQ-Grundlage erstellt wird, aber LINQ ist viel mehr. Ich benutze LINQ zu SQL nicht, dennoch benutze ich LINQ die ganze Zeit.

Nehmen Sie die Aufgabe, die Kreuzung von zwei Listen zu finden:

Vor LINQ, diese Aufgaben erfordern eine verschachtelte foreach zu schreiben, die die kleine Liste für jedes Element in der großen Liste O (N * M) einmal iteriert, und dauert etwa 10 Zeilen Code.

foreach (int number in list1) 
{ 
    foreach (int number2 in list2) 
    { 
     if (number2 == number) 
     { 
      returnList.add(number2); 
     } 
    } 
} 

LINQ verwenden, hat es die gleiche Sache in einer Zeile Code:

var results = list1.Intersect(list2); 

Sie werden bemerken, dass nicht wie LINQ sieht, aber es ist. Sie müssen die Ausdruckssyntax nicht verwenden, wenn Sie nicht möchten.

+0

Das war gut, danke. Ich bin interessiert, in Ihren beiden Codebeispielen wäre die LINQ-Version schneller als die "Original" -Version? –

+0

LINQ wird die Komplexität der Zeit jedoch nicht magisch nehmen. Also, ja, es sieht schöner aus, aber wenn es optimiert ist, ist es nur ein wenig. – mmcdole

+1

Was ist nett, weil ich die Ausdruckssyntax hasse. –

2

Der Punkt ist, dass LINQ Ihre Abfragen in Ihre primäre Programmiersprache integriert, so dass Ihre IDE Ihnen einige Möglichkeiten (zB Intellisense und Debug-Unterstützung) zur Verfügung stellt, die der Compiler eingeben kann - Überprüfen Sie Ihren SQL-Code (was bei einer normalen String-Abfrage nicht möglich ist).

+0

Aber immer noch, warum wollen Sie in LINQ SQL-Code schreiben? Wie würdest du die Leistung einstellen? Als Datenbankperson bin ich bei dem Fragesteller. Ich verstehe einfach nicht, warum Sie das aus einer Datenbankperspektive machen wollen. Die Abfragen, die ich von LINQ gesehen habe, sehen für mich aufgebläht aus. – HLGEM

+1

Wenn Sie ein ORM (* any * ORM) verwenden, werden die Abfragen aufgebläht. Wenn Sie Bare-Metal verwenden möchten, sollten Sie SQL über ADO.NET verwenden (was in einigen kritischen Codeabschnitten immer möglich ist, selbst wenn Sie hauptsächlich LINQ verwenden). – TheSmurf

+0

Ein weiterer Grund für die Verwendung von linq ist, dass die SQL-Engine-Autoren möglicherweise eine kleinere Menge von Abfrage-Mustern haben, um intern zu optimieren, was auch immer schön wäre, wie aufgebläht die Abfrage auch sein mag. –

5

Also die wirklich, wirklich große Sache über LINQ hat nichts mit Linq zu SQL zu tun. Es geht um die Verbesserungen, die es an die C# -Sprache selbst gebracht hat.

+1

VB.NET hat es auch – Larsenal

5

LINQ ist nicht nur ein ORM-System, da Jonathan darauf hinweist, dass es viele funktionale Programmierelemente zu C# bringt. Und es lässt Sie eine Menge "Datenbank-y" Sachen im normalen C# Code tun. Es ist schwer zu erklären, wie unglaublich mächtig das sein kann. Überlegen Sie, inwieweit solide, gut gestaltete generische Datenstrukturen (wie Liste, Stapel, Wörterbuch/Hash usw.), die in gängigen Frameworks enthalten sind, den Entwicklungsstand moderner Sprachen verbessert haben. Gerade weil die Verwendung dieser Datenstrukturen sehr gebräuchlich ist und der intellektuelle Aufwand, sie zu verwenden, reduziert wird, ist ein großer Vorteil. LINQ macht nichts, was Sie nicht selbst tun können, aber es macht viele Operationen viel einfacher und viel einfacher.

Betrachten Sie das altehrwürdige Beispiel zum Entfernen von Duplikaten aus einer nicht geordneten Liste. In einer niedrigeren Programmiersprache wie C oder C++ müssten Sie die Liste wahrscheinlich sortieren und zwei Indizes in der Liste beibehalten, wenn Sie die Duplikate entfernen. In einer Sprache mit Hashes (Java, C#, Javascript, Perl usw.) könnten Sie einen Hash erstellen, bei dem die Schlüssel die eindeutigen Werte sind, und dann die Schlüssel in eine neue Liste extrahieren.Mit LINQ können Sie dies nur tun:

int[] data = { 0, 1, 3, 3, 7, 8, 0, 9, 2, 1 }; 

var uniqueData = data.GroupBy(i => i).Select(g => g.Key); 
+3

Oder noch besser: data.Distinct(); –

20

Bevor:

// Init Movie 
m_ImageArray = new Image[K_NB_IMAGE]; 

Stream l_ImageStream = null; 
Bitmap l_Bitmap = null; 

// get a reference to the current assembly 
Assembly l_Assembly = Assembly.GetExecutingAssembly(); 

// get a list of resource names from the manifest 
string[] l_ResourceName = l_Assembly.GetManifestResourceNames(); 

foreach (string l_Str in l_ResourceName) 
{ 
    if (l_Str.EndsWith(".png")) 
    { 
     // attach to stream to the resource in the manifest 
     l_ImageStream = l_Assembly.GetManifestResourceStream(l_Str); 
     if (!(null == l_ImageStream)) 
     { 
      // create a new bitmap from this stream and 
      // add it to the arraylist 
      l_Bitmap = Bitmap.FromStream(l_ImageStream) as Bitmap; 
      if (!(null == l_Bitmap)) 
      { 
       int l_Index = Convert.ToInt32(l_Str.Substring(l_Str.Length - 6, 2)); 
       l_Index -= 1; 
       if (l_Index < 0) l_Index = 0; 
       if (l_Index > K_NB_IMAGE) l_Index = K_NB_IMAGE; 
       m_ImageArray[l_Index] = l_Bitmap; 
      } 
      l_Bitmap = null; 
      l_ImageStream.Close(); 
      l_ImageStream = null; 
     } // if 
    } // if 
} // foreach 

Nach:

Assembly l_Assembly = Assembly.GetExecutingAssembly(); 

//Linq is the tops 
m_ImageList = l_Assembly.GetManifestResourceNames() 
    .Where(a => a.EndsWith(".png")) 
    .OrderBy(b => b) 
    .Select(c => l_Assembly.GetManifestResourceStream(c)) 
    .Where(d => d != null) //ImageStream not null 
    .Select(e => Bitmap.FromStream(e)) 
    .Where(f => f != null) //Bitmap not null 
    .ToList(); 

Oder alternativ (Abfragesyntax):

Assembly l_Assembly = Assembly.GetExecutingAssembly(); 

//Linq is the tops 
m_ImageList = (
    from resource in l_Assembly.GetManifestResourceNames() 
    where resource.EndsWith(".png") 
    orderby resource 
    let imageStream = l_Assembly.GetManifestResourceStream(resource) 
    where imageStream != null 
    let bitmap = Bitmap.FromStream(imageStream) 
    where bitmap != null) 
    .ToList(); 
+0

+1, Ausgezeichnetes Beispiel! – missingfaktor

+2

Das Vorher-Beispiel ist ausführlicher, hat aber den Vorteil, debugfähig zu sein. Es kann schwierig sein, komplexe linq-Anweisungen zu analysieren und zu reparieren, weil sie so viel vom Entwickler verstecken. –

+2

@Phil, ja und nein, je mehr Zeilen Code Sie haben, desto mehr Debugging gibt es auch! Allerdings bevorzuge ich die Methodensyntax (erstes der After-Beispiele), weil es einfach ist, die Methodenkette an jeder Stelle in zwei Teile zu splitten. – Benjol

4

Sein Ursache Linq ist wirklich Monaden in Sql Kleidung, ich verwende es auf ein Projekt, um asynchrone Web-Anfragen mit der Continuation Monad zu machen, und es erweist sich als wirklich gut!

Schauen Sie sich diese Artikel: http://www.aboutcode.net/2008/01/14/Async+WebRequest+Using+LINQ+Syntax.aspx http://blogs.msdn.com/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx

Vom ersten Artikel:

var requests = new[] 
    { 
     WebRequest.Create("http://www.google.com/"), 
     WebRequest.Create("http://www.yahoo.com/"), 
     WebRequest.Create("http://channel9.msdn.com/") 
    }; 

    var pages = from request in requests 
       select 
        from response in request.GetResponseAsync() 
        let stream = response.GetResponseStream() 
        from html in stream.ReadToEndAsync() 
        select new { html, response }; 

    foreach (var page in pages) 
    { 
     page(d => 
     { 
      Console.WriteLine(d.response.ResponseUri.ToString()); 
      Console.WriteLine(d.html.Substring(0, 40)); 
      Console.WriteLine(); 
     }); 
    }