2009-04-02 13 views
7

Wie nehme ich eine DataTable und konvertiere sie in eine Liste?DataTable zur Liste <object>

Ich habe einige Code unten sowohl in C# und VB.NET enthalten, das Problem mit diesen beiden ist, dass wir ein neues Objekt erstellen, um die Daten zurückzugeben, die sehr teuer ist. Ich muss einen Verweis auf das Objekt zurückgeben.

Das DataSetNoteProcsTableAdapters.up_GetNoteRow-Objekt implementiert die INote-Schnittstelle.

Ich bin mit ADO.NET, zusammen mit .NET 3.5

C# -Code

public static IList<INote> GetNotes() 
{ 
    DataSetNoteProcsTableAdapters.up_GetNoteTableAdapter adapter = 
     new DataSetNoteProcsTableAdapters.up_GetNoteTableAdapter(); 
    DataSetNoteProcs.up_GetNoteDataTable table = 
     new DataSetNoteProcs.up_GetNoteDataTable(); 

    IList<INote> notes = new List<INote>(); 

    adapter.Connection = DataAccess.ConnectionSettings.Connection; 
    adapter.Fill(table); 

    foreach (DataSetNoteProcs.up_GetNoteRow t in table) { 
     notes.Add((INote)t); 
    } 

    return notes; 
} 

VB.NET-Code

Public Shared Function GetNotes() As IList(Of INote) 
    Dim adapter As New DataSetNoteProcsTableAdapters.up_GetNoteTableAdapter 
    Dim table As New DataSetNoteProcs.up_GetNoteDataTable 

    Dim notes As IList(Of INote) = New List(Of INote) 

    adapter.Connection = DataAccess.ConnectionSettings.Connection 
    adapter.Fill(table) 

    For Each t As DataSetNoteProcs.up_GetNoteRow In table 
     notes.Add(CType(t, INote)) 
    Next 

    Return notes 
End Function 
+0

Gibt es Gründe, warum Sie nicht LINQ2SQL für diese Verwendung? –

+0

Dup: http://stackoverflow.com/questions/545328/datatable-to-generic-list-memory-leak/545429#545429 –

+0

Der Kunde möchte LINQ2SQL oder LINQ generell nicht verwenden. Danke für den Link, es wird eine Menge helfen. Ich werde einige Male laufen und sehen, was passiert – Coppermill

Antwort

2

Nein, das Erstellen einer Liste ist nicht teuer. Im Vergleich zum Erstellen der Datentabelle und zum Abrufen der Daten aus der Datenbank ist es sehr günstig.

Sie können es sogar billiger von der Erstellung der Liste, nachdem die Tabelle bevölkern, so dass Sie die Anfangskapazität auf die Anzahl der Zeilen festlegen, die Sie in sie setzen wird:

IList<INote> notes = new List<INote>(table.Rows.Count); 
+0

zurückgegeben werden sicherlich meinen Sie IList Hinweise = new List (table.Rows) wenn Sie das tun Sie folgende Fehlermeldung erhalten ‚Public Sub New (Sammlung AsIEnumerable (Of IHinweis)) ': Implizite Konvertierungen von' DataRowCollection 'zu' IEnumerable (Of INote) '. – Coppermill

+5

Nein, er meint, was er geschrieben hat. Dadurch wird die Liste auf die Größe der Ergebnismenge festgelegt. – Jake

-1

Wenn die Eigenschaften der Liste der Feldnamen übereinstimmen In der Datentabelle sollten Sie in der Lage sein, eine Art generische Reflektionsroutine zu erstellen.

+0

Aber ist nicht erforderlich, ein neues Objekt zu erstellen, muss es auf das Objekt verweisen. – Coppermill

0

Möchten Sie die Zeilen der Tabelle referenzieren? In diesem Fall sollten Sie die DataTable.Rows-Eigenschaft verwenden.

Versuchen Sie folgendes:

notes.AddRange(table.Rows); 

Wenn die Tabellenzeilen IHinweis implementieren dann sollte diese Arbeit.

Alternativ könnten Sie tun, wie Sie oben haben:

foreach (INote note in table.Rows) 
{ 
    notes.Add(note) 
} 
+0

Dies ist auf table.Rows Warnung Laufzeitfehler können auftreten, wenn ‚System.Data.DataRowCollection‘ to ‚System.Collections.Generic.IList (Of.INote)‘ Umwandeln Dies ist ein neues Objekt zu erzeugen, was ich versuche zu vermeiden – Coppermill

+0

Nein, das sollte keine neuen Objekte erstellen. Alles, was Sie tun, ist das Objekt auf einen anderen Typ zu übertragen. –

1

Warum passieren nicht die Datatable in auf die Funktion, anstatt es zu instanziieren? Das würde einfach eine Referenz enthalten.

Das ist viel zu einfach eine Antwort auch lohnenswert für Sie Ich bin mir sicher, aber ich sehe nicht, wie es Ihr Problem nicht löst.

+0

Ich bin nach einer IHinweis – Coppermill

1

Nein sicher, ob dies ist was du suchst, aber du könntest so etwas versuchen.

public class Category 
{ 
    private int _Id; 
    public int Id 
    { 
     get { return _Id; } 
     set { _Id = value; } 
    } 

    private string _Name = null; 
    public string Name 
    { 
     get { return _Name; } 
     set { _Name = value; } 
    } 

    public Category() 
    {} 

    public static List<Category> GetCategories() 
    { 
     List<Category> currentCategories = new List<Category>(); 

     DbCommand comm = GenericDataAccess.CreateTextCommand(); 
     comm.CommandText = "SELECT Id, Name FROM Categories Order By Name"; 
     DataTable table = GenericDataAccess.ExecuteSelectCommand(comm); 

     foreach (DataRow row in table.Rows) 
     { 
      Category cat = new Category(); 
      cat.Id = int.Parse(row["Id"].ToString()); 
      cat.Name = row["Name"].ToString(); 
      currentCategories.Add(cat); 
     } 
     return currentCategories; 
    } 
} 

Dies ist, was ich getan habe, also hoffe das hilft. Nicht sicher, ob es der richtige Weg ist, aber es funktioniert für das, wofür wir es brauchten.

+0

Dies erzeugt ein neues Objekt, ich brauche den Code, um das Objekt zu referenzieren Kategorie cat = new Category(); Fast wie Kategorie cat = (Liste ) tables.Rows Aber das funktioniert nicht – Coppermill

+0

mit, dass Sie zuordnen können, welche Attribute Sie verwenden möchten. das ist ein größerer Ansatz, aber nicht schlecht –

6

Ich habe einen anderen Ansatz, der einen Blick wert sein könnte. Es ist eine Hilfsmethode. Erstellen Sie eine benutzerdefinierte Klassendatei namens CollectionHelper:

public static IList<T> ConvertTo<T>(DataTable table) 
    { 
     if (table == null) 
      return null; 

     List<DataRow> rows = new List<DataRow>(); 

     foreach (DataRow row in table.Rows) 
      rows.Add(row); 

     return ConvertTo<T>(rows); 
    } 

Stellen Sie sich vor, Sie möchten eine Liste von Kunden erhalten.Jetzt haben Sie die folgenden Anrufer:

List<Customer> myList = (List<Customer>)CollectionHelper.ConvertTo<Customer>(table); 

Die Attribute, die Sie in Ihrer Datentabelle haben müssen Ihre Kundenklasse (Felder wie Name, Adresse, Telefon) entsprechen.

Ich hoffe, es hilft!

Für die bereit sind, zu wissen, warum Listen zu verwenden, anstatt Tables: link text

Die vollständige Probe:

http://lozanotek.com/blog/archive/2007/05/09/Converting_Custom_Collections_To_and_From_DataTable.aspx

+1

stackoverflow nur erlauben mir, Ihnen einen Punkt zu geben, 2 ++ –

+0

kann diese Konvertierung mit einem Datenreader durchgeführt werden? –

+0

Ich war auf Wanderschaft, wenn es möglich ist, diese "muss passen" für Klassenattribute und datierbar Felder zu vermeiden! –

Verwandte Themen