2009-04-02 11 views
7

Jak wziąć DataTable i przekonwertować go na listę?DataTable do listy <object>

Załączam kod poniżej zarówno w C#, jak i VB.NET. Problem z obiema z nich polega na tym, że tworzymy nowy obiekt, który zwraca dane, co jest bardzo kosztowne. Muszę zwrócić referencję do obiektu.

Obiekt DataSetNoteProcsTableAdapters.up_GetNoteRow implementuje interfejs INote.

Używam ADO.NET, wraz z .NET 3.5

C# kodu

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; 
} 

kod VB.NET

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

Każdy powód dlaczego nie używasz LINQ2SQL do tego? –

+0

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

+0

Klient nie chce używać LINQ2SQL lub LINQ ogólnie. Dzięki za link, to bardzo pomoże. Mam zamiar uruchomić kilka razy i zobaczyć, co się stanie – Coppermill

Odpowiedz

2

Nie, tworzenie listy nie jest kosztowne. W porównaniu do tworzenia tabeli danych i pobierania danych z bazy danych, jest to bardzo tanie.

Można zrobić to taniej nawet o stworzenie listy po wypełniania tabeli, dzięki czemu można ustawić początkowe zdolności do liczby wierszy, które będzie można umieścić w nim:

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

pewnie masz na myśli IList notatki = new List (table.Rows) jeśli nie pojawi się następujący błąd „Sub New (kolekcja Public AsIEnumerable (z IWskazówka)) ": niejawne konwersje z" DataRowCollection "na" IEnumerable (Of INote) ". – Coppermill

+5

Nie, on ma na myśli to, co napisał. To spowoduje, że lista zostanie ustawiona na rozmiar zbioru wyników. – Jake

-1

Jeśli właściwości listy dopasować nazwy pól w datatable powinieneś być w stanie stworzyć rodzaj ogólnej rutyny refleksyjnej.

+0

Ale nie trzeba tworzyć nowego obiektu, musi on odwoływać się do obiektu. – Coppermill

0

Czy chcesz odwołać się do wierszy tabeli? W takim przypadku należy użyć właściwości DataTable.Rows.

Spróbuj tego:

notes.AddRange(table.Rows); 

Jeśli wiersze tabeli wdrożenia IWskazówka to powinno działać.

Ewentualnie można zrobić tak jak powyżej:

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

to jest table.Rows ostrzegawcze błędów środowiska wykonawczego może wystąpić przy konwersji „System.Data.DataRowCollection” do „System.Collections.Generic.IList (Of.INote)” to generowania nowego obiektu właśnie tego staram się unikać – Coppermill

+0

Nie, nie powinno to tworzyć nowych obiektów. Wszystko, co robisz, to rzut obiektu na inny typ. –

1

Dlaczego nie przekazać DataTable się do funkcji zamiast uruchamianiu tego go? To po prostu zawiera odniesienie.

To zbyt prosta odpowiedź też jest dla ciebie warta, jestem pewien, ale nie widzę, jak to nie rozwiązuje twojego problemu.

+0

Jestem po przeprowadzeniu IWskazówka zostać zwrócone – Coppermill

1

Nie jestem pewien, czy to jest to, czego szukasz, ale możesz spróbować czegoś takiego.

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; 
    } 
} 

Oto, co zrobiłem, więc mam nadzieję, że to pomoże. Nie jestem pewien, czy to właściwy sposób, ale działa to, czego potrzebowaliśmy.

+0

Generuje nowy obiekt, potrzebuję kodu do odwołania do obiektu Kategoria cat = new Category(); Prawie jak kategoria CAT = (lista ) tables.Rows Ale to nie zadziała – Coppermill

+0

z tym można odwzorować atrybuty, które chcesz używać. to jest większe podejście, ale nie złe –

6

Mam inne podejście, które warto rzucić okiem. Jest to metoda pomocnicza. Tworzenie niestandardowego pliku klasę o nazwie 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); 
    } 

Wyobraź chcesz uzyskać listę klientów.Teraz masz następujące osoby dzwoniącej:

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

atrybuty masz w DataTable musi dopasować swoją klasę klienta (pola, takie jak nazwa, adres, telefon).

Mam nadzieję, że to pomoże!

Dla kogo są chętni aby wiedzieć, dlaczego zamiast używać list z DataTables: link text

Pełne próbki:

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

+1

Stackoverflow pozwala mi tylko dać ci jeden punkt, 2 ++ –

+0

czy to może być konwersja z datareaderem? –

+0

Błąkałem się, jeśli można uniknąć tego "musi pasować" dla atrybutów klas i pól danych! –

Powiązane problemy