Laden...

SQL in List<T>

Erstellt von Bonaqua vor einem Jahr Letzter Beitrag vor einem Jahr 507 Views
B
Bonaqua Themenstarter:in
35 Beiträge seit 2011
vor einem Jahr
SQL in List<T>

Hallo,

ich versuche eine SQL Abfrage als List<T> zurückzugeben.


 private void button1_Click(object sender, EventArgs e)
        {
            List<Produkte> a = null;
            MySqlConnection conn = new MySqlConnection(connection);
            MySqlCommand cmd = new MySqlCommand(query, conn);

            using (conn)
            {
                MySqlDataReader dbReader; 
                conn.Open();
                dbReader = cmd.ExecuteReader();
                a = GetList<Produkte>(dbReader);
            }
            if (a != null)
            {
                dataGridView1.DataSource = a;
            }

        }


        public static List<T> GetList<T>(IDataReader reader)
        {
            List<T> list = new List<T>();
            while (reader.Read())
            {
                var type = typeof(T);
                T obj = (T)Activator.CreateInstance(type);
                foreach (var prop in type.GetProperties())
                {
                    var propType = prop.PropertyType;
                    prop.SetValue(obj, Convert.ChangeType(reader[prop.Name].ToString(), propType));
                }
                list.Add(obj);
            }
            return list;
        }

Allerdings erhalte ich die Fehlermeldung: > Fehlermeldung:

Keine Überladung für die SetValue-Methode nimmt 2 Argumente an.

Kann mir bitte jemand helfen, wie ich das Problem lösen kann??

2.079 Beiträge seit 2012
vor einem Jahr

Die Methode mit zwei Parametern gibt's seit .NET 4.5 - was verwendest Du?
Schau dir die IntelliSense-Hilfe an, da zeigt dir Visual Studio an, welche Überladungen es gibt - dann nimm eine davon.
Oder Du verwendest eine aktuelle Version, das wäre am klügsten und Du hast das Problem nicht mehr.

Und was Du da tust, gibt's schon, man nennt es OR-Mapper.
Und von Microsoft gibt's das Entity Framework.
Oder Du verwendest Dapper, wenn es etwas leichtgewichtiges sein soll.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

B
Bonaqua Themenstarter:in
35 Beiträge seit 2011
vor einem Jahr

Danke für Deine Antwort. So etwas in die Richtung habe ich befürchtet.
Das Problem ist, dass das Projekt mit .NET 4.0 und VS2010 erstellt wurde und auch so läuft.
Darin wurde auch das Entity Framework verwendet.
Aber einfach auf eine neuere VS Version upgraden geht ja leider nicht so einfach. Daher
war eine Überlegung, die Datenbankabfragen nicht mehr über das EF zu machen, sondern direkt
per SQL. Dat hat auch bei Abfragen zu einer deutichen Verbesserung der Performance geführt.
So könnte dann auch einfacher auf eine neuere Version des Visual Studio umgestellt werden.

Hab ich sonst noch eine Möglichkeit, unter meinen gegeben Umständen ein Objekt <T>
und/oder eine List<T> zurückgeben zu lassen?

2.079 Beiträge seit 2012
vor einem Jahr

Tja, willkommen in der Wirklichkeit 😁
Je länger man Updates vor sich her schiebt, desto aufwändiger/schwieriger wird es, bis es kaum noch tragbar ist.
Aber ganz ehrlich: Wenn Du "mal eben so" die komplette Daten-Schicht samt Entity Framework neu selber basteln kannst, dann kannst Du auch die Versionen hoch ziehen, das ist weniger riskant.

Aber einfach auf eine neuere VS Version upgraden geht ja leider nicht so einfach.

Doch - warum nicht?

Dat hat auch bei Abfragen zu einer deutichen Verbesserung der Performance geführt

Das alte Entity Framework war nie sonderlich performant.
Das neue Entity Framework Core ist eine Neuentwicklung, immer noch nicht auf dem Level von plain SQL, aber deutlich schneller, als das alte.

Hab ich sonst noch eine Möglichkeit, unter meinen gegeben Umständen ein Objekt <T>
und/oder eine List<T> zurückgeben zu lassen?

Ja:

Schau dir die IntelliSense-Hilfe an, da zeigt dir Visual Studio an, welche Überladungen es gibt - dann nimm eine davon.

Aber Du solltest lieber aktualisieren, als auf dem selben altbackenem Kram herum zu kriechen.
Wenn Du dir das selber bastelst, bastelst Du dir nur das nächste Problem.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

4.939 Beiträge seit 2008
vor einem Jahr

Verwende einfach die Methode mit drei Parametern SetValue(Object, Object, Object[]) und übergebe null als letzten Parameter.

Ich hoffe, das ist nur ein Testprojekt, denn der Datenbankcode gehört nicht in den UI-Code (s. [Artikel] Drei-Schichten-Architektur)?!

Außerdem stimme ich Palladin007 zu.

16.832 Beiträge seit 2008
vor einem Jahr

Das neue EF ist schon sehr nahe an einer fast impactlosen Performance für SQL Abfragen selbst.
Aber natürlich kostet das Serialisieren Zeit - egal ob man es über EF oder über einen manuellen Weg macht.

Die Kunst in der alten und auch in der neuen Welt ist, die Abfragen performant zu gestalten - das gleiche gilt für Dapper.
Wenn man als Entwickler aber das System nicht versteht, muss man das System nicht beschuldigen, dass es langsam läuft.

Und wenn man

Daher war eine Überlegung, die Datenbankabfragen nicht mehr über das EF zu machen, sondern direkt
per SQL. Dat hat auch bei Abfragen zu einer deutichen Verbesserung der Performance geführt.

liest, dann liegt das nahe, dass die dafür verantwortliche Person dies offenbar nicht im Griff hatte 😉

Statt also das Rad neu zu erfinden und evtl selbst konzeptionelle Fehler zu begehen, ist es ratsamer, einfach das System zu (er)lernen.
Der gezeigte Code im Eingangspost ist xxxx-fach langsamer als jede EF / Dapper Implementierung.

J
641 Beiträge seit 2007
vor einem Jahr

Wenn es rein um die Perfomance geht, oder du einfach nur einen ORM Mapper für Typisierte SQL Abfragen brauchst, kann ich auch noch linq2db empfehlen (https://github.com/linq2db/linq2db). Das bietet Typsicheres SQL via Linq wie EFCore auch, aber häufig ein klein bisschen performanter, jedoch auch mit weniger features (wie z.b. kein Change Tracking)

cSharp Projekte : https://github.com/jogibear9988

2.079 Beiträge seit 2012
vor einem Jahr

Ich würde aber nicht auf LINQ2DB setzen, einfach nur weil man denkt, dass es um Performance geht.

Ich traue Microsoft zu, dass sie das sehr gut können und ich traue Abt zu, dass seine Aussage (fast impactlose Performance) auf Erfahrungen beruht, die eine solche Aussage rechtfertigen.
Vielleicht ist LINQ2DB ein wenig schneller, aber rechtfertigt dieser Vorteil, dass man auf EFCore mit allen seinen Vorteilen und Change Tracking (was man auch abschalten kann) verzichten muss?
Ganz ehrlich: Dieses Framework bildet den Kern der Anwendung, der sollte sitzen und da setze ich lieber auf EFCore, das weit weit umfangreicher getestet ist, weil es ungefähr überall genutzt wird.

Wenn die Performance wirklich derart wichtig ist, dann würde ich lieber direkt auf Dapper setzen, aber auch da: Lohnt sich der Aufwand wirklich?

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

16.832 Beiträge seit 2008
vor einem Jahr

LINQ2DB ist gegenüber EFCore nur in ganz ganz wenigen, teilweise nicht-realen Szenarien schneller. Arbeitet man in einem üblichen Umfang mit einer DB (Lesen, Schreiben, Aktualisieren) und verwendet entsprechende Entitäten, dann ist Linq2DB in der Gesamtlösung nicht schneller. Vor allem EF Core 6 hat einen riesen Sprung bei der Performance gemacht, das eh schon Welten schneller war als EF6. https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-6-0-preview-4-performance-edition Ich war nie ein großer Freund von EF6, da hab ich auch lieber Linq2DB gemacht - aber ausser dem Namen hat EFCore nichts mehr mit der alten Welt zutun und ist mein #1 ORM heute. Auch dieses Forum basiert vollständig auf EF Core 6 (bzw. teilweise schon EF 7 Preview) und der EF Impact gegenüber Plain SQL is unter 2%. Hat mich durchaus Zeit gekostet die ganzen Optimierungen zu verstehen etc - aber es funktioniert. Die Lib also für schlechte Performance verantwortlich zu machen offenbart eher eigenes Unverständnis.

Der Gap zwischen einem reinen Serialization Framework wie Dapper mit einem voll-funktionalen ORM wie EF ist so verschwindend gering, dass man das in 99% der Anwendungen nicht messen geschweige denn merken kann.
Denn für die Performance einer Anwendung spielen mehrere Faktoren eine Rolle, nicht nur das Absenden eines Queries.

Wer um den DB Code ineffizient programmiert, programmiert um den DB Code ineffizient. Dann ist es völlig egal, was man für den DB Code verwendet.
Rein sachlich, basierend auf den tausenden Projekten, die ich gesehen habe, wirklich nicht persönlich:
Wenn ich Quellcode sieht wie


private void button1_Click(object sender, EventArgs e)
       {
           List<Produkte> a = null;
           MySqlConnection conn = new MySqlConnection(connection);
           MySqlCommand cmd = new MySqlCommand(query, conn);

           using (conn)
           {
               MySqlDataReader dbReader;
               conn.Open();

bzw.


List<T> list = new List<T>();
           while (reader.Read())
           {
               var type = typeof(T);
               T obj = (T)Activator.CreateInstance(type);
               foreach (var prop in type.GetProperties())
               {
                   var propType = prop.PropertyType;
                   prop.SetValue(obj, Convert.ChangeType(reader[prop.Name].ToString(), propType));
               }
               list.Add(obj);
           }

*dann liegt es nahe, dass der sonstige Quellcode vielleicht auch nicht so wirklich effizient und sauber ist und die EF-Fehler vielleicht eher die geringeren sind, die schlechte Performance verantworten 😉
Ist jetzt evtl je nach Projekt nicht schlimm; aber dann der Performance-Keule kommen ist vielleicht nicht so das Gelbe vom Ei 🙂

Frage wird also am Ende eher sein: will der/die Thread-Starter/in wirklich ein gut gereiften ORM verstehen, lernen und anwenden - oder will er/sie alles selbst machen.

* ist super ineffizienter Quellcode, sowohl technisch wie auch logisch.
Der größte Impact dürften die konzeptionellen Fehler rund um die Typ-Behandlung sein, zB. dass in der Schleife wieder und wieder der Typ und dessen Eigenschaften ermittelt wird.
Das allein wird wahrscheinlich mehr Performance kosten als der SQL Befehl selbst.

Das ist auch ohne eine Type-Caching Infrastruktur**nicht effizient zu lösen.
Ebenso kann man das Listen-Handling 1000-fach performanter und Ressourcen-schonender umsetzen, zB mit IEnumerable und yields. So, wie es hier ist, führt es zu ständigem Array hin-und-her-kopiere bei umfangreicheren Rückgaben => big impact.

**EF löst dies entweder durch eben solch eine Caching-Infrastruktur der Entitäten, oder aber durch die optionale Verwendung von Compiled Models.
https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-6-0-preview-5-compiled-models/
Meiner Erfahrung nach lohnt sich aber erst ab einer gewissen Anzahl von Modellen >500-1000

J
641 Beiträge seit 2007
vor einem Jahr

Vielleicht ist LINQ2DB ein wenig schneller, aber rechtfertigt dieser Vorteil, dass man auf EFCore mit allen seinen Vorteilen und Change Tracking (was man auch abschalten kann) verzichten muss?
Ganz ehrlich: Dieses Framework bildet den Kern der Anwendung, der sollte sitzen und da setze ich lieber auf EFCore, das weit weit umfangreicher getestet ist, weil es ungefähr überall genutzt wird.

Kommt halt darauf was für features man braucht. Und es gibt eben noch andere Frameworks als EF-Core, das wollte ich eben erwähnen.
Auch linq2db ebenso durch tausende Tests abgedeckt.
Ich hatte (es zumindest früher), häufig so das ich viele features in SQL nicht mit EF-Core als linq abbilden konnte. Da war zu der Zeit linq2db weiter (Merge, Window Functions). Weiß nicht wie da der aktuelle Stand mit EF-Core ist, wir haben uns EF-Core dann nicht mehr angeschaut.

cSharp Projekte : https://github.com/jogibear9988

16.832 Beiträge seit 2008
vor einem Jahr

Da war zu der Zeit linq2db weiter (Merge, Window Functions). Weiß nicht wie da der aktuelle Stand mit EF-Core ist, wir haben uns EF-Core dann nicht mehr angeschaut.

Viele Window Functions aka Analytic Functions existieren seit den ersten Tagen, andere werden als CROSS APPLY umgesetzt.
Generell macht es jedoch nicht unbedingt viel sinn* solche Functions direkt in EF mit Linq umzusetzen (eigentlich gar nicht); sondern das ist eine der Fälle, bei denen eine Stored Proc mehr sinn macht, die dann via ORM aufgerufen wird.

*Grund ist: gerade analytische Funktionen ändern sich gerne mit DB Versionen, sodass spezifische Programmierung mit einer nativen Technologie bessere Ergebnisse liefert, als generisches Zeug auf (T)-SQL Basis.
Das kann kein ORM abdecken, dafür ist er auch nicht gedacht.