Linq-Abfrage sehr langsam
-
Hallo,
ich führe folgende Abfrage aus
var query = from v in ctx.v_completedata join a in ctx.a_identity on v.ident equals a.ident join l in ctx.l_place on v.placeId equals l.Pid orderby v.ident select new Member { Membernumber = v.ident, Membername = a.name, Place = l.house, PlaceId = v.placeId }; DataTable tbl = IEnumerableToDataTable.ToDataTable(query.ToList()); return tbl;
Die Tabellen v_completedata und a_identity haben jeweils ~7500 Datensätze.
Die Tabelle l_place ca. 160 Datensätze.Die Daten werden wie folgt gebunden:
DataTable table = GetMemberPlace(); dgMemberPlace.DataSource = table;
Bis alle Daten angezeigt werden, dauert es etwa 15 Sekunden.
Was kann ich tun, damit das ganze etwas schneller wird?
Bzw. woran kann das liegen?Danke!
-
Hast du schon mal geprüft, wo die große Zeit verbraucht wird? Ich vermute nämlich, das es das binden ans DGV ist und nicht die Linq-Abfrage.
-
Die Zeit wird wirklich bei der Abfrage verbraucht ...
Ich habe mir schon überlegt, ob ich mal versuchen soll, die Query vorzukompilieren?
-
Leider macht das die ganze Sache auch nicht schneller
-
Was genau macht denn die Funktion ToDataTable()? Normal sollte die Abrfrage nicht allzulange dauern.
Alternativer Vorschlag: Statt die Daten in C# zusammenzubauen, könntest du auch eine View in SQL bauen, die dir die nötigen Daten zurückliefert und diese dann einfach über deinen Context auslesen.
-
Hallo,
ich habe mir mit der Zeit abgewöhnt über LINQ abzufragen weil sehr viel überflüssiges Zeugs generiert wird was ich schwer beeinflussen kann. Wir haben es aus Performancegründen an den meisten Stellen so gelöst:
List<T> tmp = (from row in db.ExecuteStoreQuery<T>("SELECT * FROM bla bla bla").ToList() bla bla bla)
T ist deine Klasse
Das geht rasend schnell und wenn nicht, dann liegt es schon nicht mehr an LINQ sondern an deiner Datenbank oder an der Verbindung dorthin.
Nachteil an dieser Sache:
- Updaten oder Inserten oder Deleten ist nicht mehr möglich
- Du musst ne neue Klasse zum "mappen" anlegen
- Empfiehlt sich nur dann, wenn man Daten anzeigen aber nicht bearbeiten will
-
@secondsun
Super, vielen Dank! So geht die Abfrage nun richtig schnell... wie es sein soll!Allerdings tritt nun folgendes Problem auf und ich weiß nicht, woran das liegt.
Ich habe eine eigene Klasse Identity geschrieben.
public class Identiy { public string MemberNumber { get; set; } public string MemberName { get; set; } public string Place { get; set; } public string PlaceId { get; set; } ...
var result = context.ExecuteStoreQuery<Identity>(sQuery); dgMemberPlace.DataSource = result;
Die Abfrage selbst stimmt und läuft unter MySQL einwandfrei.
Rufe ich das ganz im Programm auf, läuft es auch, allerdings bleiben die beiden Spalten MemberNumber und MemberName leer. Weshalb?
Anzahl meiner Felder in der Klasse stimmt mit der Anzahl der SELECTs überein.
-
Alles was du zurück bekommst ist auch varchar? MemberNumber klingt für mich nach einem int Wert oder so..Die Datentypen in deiner Klasse müssen übereinstimmen mit den äquivalenten SQL Datentypen.
Mach doch zum Testen mal das hier:
context.ExecuteStoreQuery<Identity>(sQuery).ToList();Dann wird dein Resultset materialisiert. Und im Debug Modus guckst du mal wie die result befüllt ist.
-
Die Datentypen stimmen (VARCHAR in der Datenbank und in der Klasse als string definiert).
Ich habe eben nachgeprüft. Im result steht null.
Selbst wenn ich nur ein einfaches SELECT für die Number und den Name mache (beides strings).
Die selbe Abfrage in MySQL liefert problemlos die Daten ...
-
Ich vermute, dass das Problem irgendwie mit meiner eigenen Klasse zusammenhängt.
Einzige Möglichkeit wie ich bisher überhaupt Daten angezeigt bekomme ist folgende:
string sQuery = "SELECT * FROM tabelle1"; var result = context.ExecuteStoreQuery<tabelle1>(sQuery).ToList(); dgMemberPlace.AutoGenerateColumns = true; dgMemberPlace.DataSource = result;
Sobald ich nur einzelne Spalten möchte, bekomme ich keine Daten mehr (Fehlermeldung).
Und wenn ich als Rückgabeklasse meine eigene Klasse Identity verwenden möchte, bekomme ich ebenfalls keine Daten,
-
Konnte das Problem lösen. Meine eigene Klasse hatte die falschen Bezeichnungen ... diese müssen wohl mit denen aus der DB übereinstimmen (jedenfalls klappt es so).
@secondsun
Nochmals danke für Deine Hilfe!
-
Jetzt habe ich doch nochmals ein Problem:
Wie fange ich mit
ExecuteStoreQuery
null Werte ab?
Ich habe eine recht komplexe Abfrage mit JOINS.
-
Oh hier ist ja wieder Bewegung drin...
Dir geht es um Felder deren Inhalt NULL ist? Würde ich in der View abfangen. In Firebird würde ich das mit CASE und IS NULL oder so machen und dafür Leerzeichen oder so eintragen. In der Anwendung würde ich es nicht tun.