Datasource an List<T> binden
-
Hallo,
so einigermaßen hat das mit dem Entity Framework geklappt, so dann ich darüber nun versuche meine Abfragen laufen zu lassen.
Nun stehe ich aber schon vor einem Problem - wie binde ich meine Daten an ein List<T>?
Gut, ich könnte einfach so machen - aber das möchte ich nicht:
... var neuBefund= from b in context.tabellebefunde orderby b.name select b; ComboBox1.DataSource = neuBefund; ...
Meine Vorstellung ist, dass ich der Methode einen Rückgabewert vom Typ IEnumerable<Befund> gebe. Folgendes habe ich versucht:
public static IEnumerable<Befund> HoleWerteAusDB() { using (dbEntities context = new dbEntities()) { List<Befund> listeBefund = new List<Befund>(); listeBefund = from b in context.tabellebefunde orderby b.name select b; //Anweisung von oben geht so nicht //hier komme ich nicht weiter //listeBefund.Add( ... ); return listeBefund; } }
Folgende Fehlermeldung
Der Typ "System.Linq.IOrderedQueryable<Test.tabellebefunde>" kann nicht implizit in "System.Collections.Generic.List<Test.Classes.Befund>" konvertiert werden.
Hoffe ihr habt mein Problem verstanden. Würde mich über Eure Antworten freuen! Danke!
-
Du kannst ToList() auf den Linq-Ausdruck anwenden.
http://msdn.microsoft.com/de-de/library/bb342261.aspx
Das hat aber zur Folge, dass keine "Deferred Execution" mehr stattfindet, sondern die Abfrage auf einen Schlag durchgeführt wird. Das kann u.U. unerwünscht sein.
-
Ansonsten mit "yield return" (innerhalb einer foreach-Schleife) arbeiten (damit der DBContext nicht vorher disposed wird).
public static IEnumerable<Befund> HoleWerteAusDB() { using (DbEntities context = new DbEntities()) { listeBefund = from b in context.tabellebefunde orderby b.name select b; foreach (var entry in listBefund) yield return entry; } }
P.S. Die Klasse sollte "DbEntities" heißen (entsprechend den Microsoft Naming Conventions), daher habe ich den Code so angepaßt!
-
Danke Euch beiden ...
Leider habe ich in beidne Fällen Probleme mit der Umwandlung
public static IEnumerable<Befund> HoleWerteAusDB() { using (DbEntities context = new DbEntities()) { List<Befund> liste = new List<Befund>(); var query = from b in context.tabellebefunde select b.Name; liste = query.Select(befund=> befund.ToString()).ToList(); return liste; } }
Eine implizite Konvertierung vom Typ "System.Collections.Generic.List<string>" in "System.Collections.Generic.List<Test.Klassen.Befund>" ist nicht möglich.
public static IEnumerable<Befund> HoleWerteAusDB() { using (DbEntities context = new DbEntities()) { var liste = from b in context.tabellebefunde select b.Name; foreach (var entry in liste) yield return entry; } }
Eine implizite Konvertierung vom Typ "Test.tabellebefund" in "Test.Klassen.Befund" ist nicht möglich.
Fehlt beides mal die Umwandlung, oder ist ein anderer Fehler drin?
-
Sonnenlichtfee schrieb:
Danke Euch beiden ...
Leider habe ich in beidne Fällen Probleme mit der Umwandlung
public static IEnumerable<Befund> HoleWerteAusDB() { using (DbEntities context = new DbEntities()) { List<Befund> liste = new List<Befund>(); var query = from b in context.tabellebefunde select b.Name; liste = query.Select(befund=> befund.ToString()).ToList(); return liste; } }
Eine implizite Konvertierung vom Typ "System.Collections.Generic.List<string>" in "System.Collections.Generic.List<Test.Klassen.Befund>" ist nicht möglich.
Hier wird mit der Funktion "Select()" vor dem ToList() "nur" ein String ermittelt, also kommt auch eine String-Liste heraus, und du willst aber eine Befund-Liste zurückgeben, dann lass die komplette Select()-Funktion weg.
Sonnenlichtfee schrieb:
public static IEnumerable<Befund> HoleWerteAusDB() { using (DbEntities context = new DbEntities()) { var liste = from b in context.tabellebefunde select b.Name; foreach (var entry in liste) yield return entry; } }
Eine implizite Konvertierung vom Typ "Test.tabellebefund" in "Test.Klassen.Befund" ist nicht möglich.
Fehlt beides mal die Umwandlung, oder ist ein anderer Fehler drin?
Hier ist es das gleiche Problem, im from...select b.Name wird definiert, das nur der Name des Objekte zurückgegeben wird, welcher warscheinlich ein String ist, dadurch wird beim yield return auch nur ein String zurück gegeben und nicht das befund-Objekt. hier einfach das "select b.Name" durch "select b" tauschen.
Mfg Marco
-
Wie Du vorgeschlagen hast, hab ich es auch schon probiert (also ohne .Select()) - wieder selbes Problem
liste = query.ToList();
Auch wenn ich nur
select b;
schreibe, hab ich wieder ein Konvertierungsproblem.
Meine Liste passt soweit, d.h. sie gibt Werte zurück (hab sie direkt als DataSource an die Combobox gehängt - ohne Probleme).
-
Ich hoffe jetzt mal, das die Klasse Befund auch aus dem Entity-Framework kommt, und nicht eine Klasse, neu definierte an einer anderen Stelle ist.
Ansonst könntest du bitte nochmal die genaue Fehlermeldung posten?
MfG Marco
-
Ich hoffe jetzt mal, das die Klasse Befund auch aus dem Entity-Framework kommt, und nicht eine Klasse, neu definierte an einer anderen Stelle ist.
Genau das war das Problem!
Danke für den Hinweis! Jetzt klappts!
-
Was muss ich bei einer Methode als Rückgabetyp angeben, um damit an anderer Stelle einen GridView befüllen zu können? Kann man das pauschal sagen? Oder gibt es mehrere Möglichkeiten?
Die Daten dafür sollen ebenfalls übers Entity Framework mittels Linq (select und join) abgefragt werden.
Abfrage steht soweit auch schonvar joinQuery = from b in context.tabellebefund join w in context.tabellewerte on b.nummer equals w.befundNr select new { w.WertHD, b.Nummer };
-
Die beiden gewünschten Werte kann ich nun auslesen (MessageBox).
Wie kann ich diese (einmal string einmal int32) so "speichern" oder übergeben, dass ich mit diesen ein GridView füllen kann?
-
Anonyme Klassen kannst du nicht über Methodengrenzen hinweg zurückgeben, d.h. du mußt dir eine Klasse (XXX) definieren und dann entsprechend IEnumerable<XXX> zurückgeben.
-
Th69 schrieb:
Anonyme Klassen kannst du nicht über Methodengrenzen hinweg zurückgeben, d.h. du mußt dir eine Klasse (XXX) definieren und dann entsprechend IEnumerable<XXX> zurückgeben.
Das ist so nicht ganz korrekt. Es gibt seit C# 4.0 das Schlüsselwort
dynamic
. Dieses kann man auch als Rückgabewert oder als Generictype Parameter verwenden.using System; using System.Collections.Generic; public class Program { public static IEnumerable<dynamic> Test() { yield return new { Test = "Hello" }; } public static void Main(string[] args) { foreach(var obj in Test()) { Console.WriteLine(obj.Test); } } }
Man sollte sich allerdings bewusst sein, dass sich dies negativ auf die Performance auswirken kann. Ist somit mit Vorsicht zu geniessen
Grüssli
-
Danke mit dem Hinweis mit
dynamic
werde ich morgen mal testen.Beim Googeln bin ich auf CopyToDataTable gestossen.
Damit sollte ich doch die Linq Abfrage einer DataTable übergeben können und diese dann an ein GridView binden können?!Dazu habe ich gesehen, dass
System.Data.DataSetExtension
eingefügt werden muss.
Den Verweis dazu kann ich auch unter Verweise in meinem Projekt sehen, überusing
kann ich es aber nicht einbinden. An was kann das liegen?
-
Edit by Dravere:
Der folgende Teilbeitrag wurde bei einer Abtrennung ebenfalls entferntDravere schrieb:
@Sonnenlichtfee,
Hast du die richtige Version eingebunden? Zum Teil gibt es Probleme, wenn man die falsche DLL Version vonSystem.Data.DataSetExtension
einbindet. Also zum Beispiel die Version für .Net 3.5 in einem .Net 4 Projekt probiert zu verwenden.Edit End
--------------------------------------
Auf dem PC wird .Net 4 verwendet.
Im VS wird beim Verweis die Version v4.0.30319 angegeben - eine andere kann ich auch nicht finden.
Dennoch kann ichusing System.Data.DataDataSetExtension;
nicht einbinden.Gibts dafür noch andere Voraussetzungen, dass es eingebunden werden kann?
-
@Sonnenlichtfee,
Oh, moment, moment, mein Fehler ...Die System.Data.DataSetExtension.dll legt ihre Objekte ja im
System.Data
Namensraum ab. Es gibt keinenSystem.Data.DataSetExtension
Namensraum! Ich arbeite zu wenig mit DataSet zusammen, hatte ich gerade ganz vergessenSiehe zum Beispiel:
http://msdn.microsoft.com/en-us/library/system.data.datatableextensions.aspxNamespace: System.Data
Assembly: System.Data.DataSetExtensions (in System.Data.DataSetExtensions.dll)Grüssli
-
@Dravere
Jetzt hab ich zumindest das eigentlich Problem gefunden - denke ich zumindestFür die Klasse aus dem Entity Framework (Befund) gibt es keine CopyToDataTable() Methode. Zumindest wird dies so nicht angeboten.
Müsste ich diese dann selbst schreiben?IEnumerable<Befund> test = from i in context.tblbefund.AsEnumerable() select i; DataTable dt = test.CopyToDataTable(); return dt;
Denn folgender Aufruf kennt die Methode dann doch (allerdings gibt es hier dann wieder ein Konvertierungsproblem)
IEnumerable<DataRow> test = from i in context.tblbefund.AsEnumerable() select i; DataTable dt = test.CopyToDataTable(); return dt;
Falls selber schreiben, an was kann ich mich da orientieren, wie das aufgebaut sein soll?
-
Das ganze wird langsam unübersichtlich...
Was willst du eigentlich erreichen? Du redest weiter vorne davon, dass du es an ein
GridView
binden möchtest. Reden wir hier von WPF?
Möchtest du also die Resultate, welche du erhälst, in einem WPFGridView
einerListView
anzeigen lassen?Grüssli
-
Ich möchte einen Rückgabewert erhalten, den ich übergeben kann und dann an ein DataGridView (WinForms) hängen kann.
Bisher habe ich dazu immer eine DataTable zurück gegeben und diese dann als DataSource an das GridView gehängt.
-
An die DataGridView.DataSource-Eigenschaft kannst du doch auch direkt eine List<XXX> o.ä. dranhängen - es muß ja keine DataTable sein.
Also in deinem Code einfachreturn test.ToList();
verwenden.
-
@Th69
Danke für den Tipp - so klappt es!Wenn ich allerdings nur einzelne Spalten selektieren möchte, bekommme ich schon wieder ein Konvertierungsproblem angezeigt.
select new { i.Befund, i.Bezeichnung };
Kann mir vielleicht jemand eine gute Seite zu Linq sagen oder hat jemand einen Buchtipp für mich?! Denke die Grundlagen in diesem Bereich fehlen bei mir total ...