2009-11-04 5 views
7

Mam problemy z łączeniem koncepcji dobrego projektowania baz danych z dobrym zorientowanym obiektowo projektem.Zwracanie danych z bazy danych w .NET: Zwrócić DataTable lub LIst <T>?

Tradycyjnie gdybym chciał, aby wyświetlić listę newsów w peryferyjnym, chciałbym użyć czegoś takiego:

<script runat="server"> 

    void ShowNews() 
    { 
     rptNewsStories.DataSource = News.GetAllNews(); // Returns a DataTable 
     rptNewsStories.DataBind(); 
    } 

</script> 

<asp:Repeater id="rptNewsStories" runat="server"> 
    <ItemTemplate> 
     <div> 
      <span class="Title"><%# Eval("Title")"%> (<%# Eval("Location")"%>)</span> 
      <p> 
       <%# Eval("Summary")"%> 
      </p> 
      <ul> 
       <li>Added by: <%# Eval("AddedByFullName")%></li> 
       <li>Added on: <%# Eval("AddedOn")%></li> 
      </ul> 
     </div> 
    </ItemTemplate> 
</asp:Repeater> 

Tutaj News.GetAllNews() zwraca DataTable, który jest po prostu dump z tego, co procedura składowana zwraca. Procedura przechowywana jest zapisywana w celu zwrócenia danych przy użyciu sprzężeń, więc jest to więcej niż jedna wartość tabel.

Ma to tę zaletę, że w bazie procedura przechowywana może wyszukać którzy dodawali historię wiadomości z AddedByID że istnieje w Aktualności stole i zwróci osobom pełną nazwę jako AddedByFullName wartości zwracanej .

Jednak gdy próbuję i upuść używania DataTable i zamiast wrócić listę obiektów Wiadomości, mam następujące:

<script runat="server"> 

    void ShowNews() 
    { 
     rptNewsStories.DataSource = News.GetAllNews(); // Returns a List<News> 
     rptNewsStories.DataBind(); 
    } 

</script> 

<asp:Repeater id="rptNewsStories" runat="server"> 
    <ItemTemplate> 
     <div> 
      <span class="Title"><%# Eval("Title")"%> (<%# Eval("Location")"%>)</span> 
      <p> 
       <%# Eval("Summary")"%> 
      </p> 
      <ul> 
       <li>Added by: <!-- Here there is only a AddedByUserID, not an AddedByFullName value --></li> 
       <li>Added on: <%# Eval("AddedOn")%></li> 
      </ul> 
     </div> 
    </ItemTemplate> 
</asp:Repeater> 

Ale teraz pozostaje mi się z problemem, że pewne wartości, które Chcę wyświetlić (podobnie jak AddedByFullName) nie istnieją w obiekcie News, ponieważ nie są one czymś jawnie ustawionym, ale nie są pobierane z identyfikatora odnośnika w obiekcie.

Chciałbym zwrócić obiekty zamiast DataTables, ale nie wiem, jak najlepiej wypełnić tę lukę.

Do I:
* Tworzenie dodatkowych właściwości w Aktualności klasy dla każdej dodatkowej wartości, która może być zwrócony z bazy danych w odniesieniu do tych danych?
* Trzymaj z DataTables dla konkretnych przypadków, gdy jest dużo dodatkowych wartości?

Czy jestem całkowicie na niewłaściwym torze!

Odpowiedz

4

Twoje wybory są ograniczone przez użytej technologii jesteś gotów użyć jako dostępu do danych. W tej chwili istnieje kilka alternatyw, które obsługuje zestaw narzędzi VS i platforma .Net:

Z tych wszystkich zestawów danych oprócz ADO.Net można określić relacje nawigacji, jak chcesz, albo chętnie lub leniwie załadowany. W przypadku takim jak ty opisujesz, że naturalnym sposobem połączenia z tymi technologiami byłoby modelowanie relacji między artykułem prasowym a autorem jawnie w projektantach i pozwolenie, aby ramy radziły sobie z problemem ładowania odpowiednich danych i do odpowiednich typów, co ostatecznie oznacza problem łączenia jest obsługiwany niejawnie przez warstwę dostępu do danych aplikacji (framework), a nie przez jawnie utworzoną procedurę przechowywaną.

Wybór technologii będzie falować wszędzie w kodzie, od sposobu pobierania danych do sposobu ich wyświetlania i sposobu aktualizacji, żadnej z tych technologii nie można łatwo wymieniać. Osobiście uważam, że właściwą równowagę między mocą i złożonością ma LINQ do SQL.

+0

Dzięki za twój wkład Remus - Słyszałem, że MS zatrzymało rozwój LINQ na SQL na rzecz Entity Framework. Czy to prawda, a jeśli tak, czy zachęcałbyś do nowych rozwiązań wykorzystujących tę technologię? –

+0

@Peter: Nie jestem już ze stwardnieniem rozsianym, tak naprawdę nie wiedziałbym więcej niż jest publiczna wiedza. Czy to prawda, że ​​EF jest zalecaną metodą w przyszłości, ale biorąc pod uwagę przytłaczające przyjęcie LINQ do SQL w porównaniu z EF, byłabym zaskoczona, widząc to całkowicie porzucone. –

+0

Obecnie używam LINQ2SQL i cieszę się nim w projekcie .net 3.5. Mój następny duży projekt będzie korzystał z .net 4.0, więc będę używać Entity Framework 4.0 –

0

Dobre pytanie:

Istnieje kilka podejść można podjąć:

  1. Można pobierać dodatkowe dane, które są potrzebne na wiążącą przypadku repeatera i wypełnić go w " symbol zastępczy "dla każdego zwróconego rekordu wiadomości. Ma to problemy z wydajnością z powodu dodatkowych zapytań, ale zadziała.

  2. Jeśli to możliwe, zmodyfikuję obiekt wiadomości tak, aby zawierał dodatkowe informacje lub utworzy obiekt, który dziedziczy z obiektu wiadomości, który zawierał dodatkowe informacje lub właściwości.

Nadzieja to pomaga :-) +1

Edycja/Komentarz: myślę tarcie widzisz w projekcie jest to, że nie uznając „ma-a” relacji między obiekt wiadomości i to, co nazwałbym jego autorem/współautorem.Łączenie, które robisz w swoim zapytaniu, polega na ukryciu braku relacji w modelu obiektowym.

+0

Dzięki za wejście Achilles: 1) Podobne do sugestii Gregoire'a. Jak ci się wydaje, że to się uda, ale ten rodzaj podejścia wydaje się tylko dodatkową pracą? 2) Wiem, że będzie to bardziej wydajne, ale nadal wydaje się trochę spiczaste ... chociaż wolę je od opcji 1 Mam nadzieję, że propozycja będzie właściwa, gdy takie podejścia nie Czuję się jak idealnie pasuje. –

+0

Myślę, że tarcie, które widzisz w swoim projekcie, polega na tym, że nie uznajesz związku "ma-a" między twoim obiektem wiadomości a tym, co nazwałbym jego autorem/współautorem. Łączenie, które robisz w swoim zapytaniu, polega na ukryciu braku relacji w modelu obiektowym. – Achilles

+0

Dobra rada, dobrze zrobione –

0

Można spróbować, może nie lepszym rozwiązaniem:

void ShowNews() 
{ 
    User[] usersConcerned = News.GetAllUsersLinkedWithNews(); //only return the users concerned by the news 
    List<News> news = News.GetAllNews(); 
    foreach(News item in news) 
    { 
     item.AddedByUser = usersConcerned.FirstOrDefault(u=>u.Id == item.AddedByUserID); 
    } 
    rptNewsStories.DataSource = news ; 
    rptNewsStories.DataBind(); 
} 
+0

Tego typu podejście przeszło mi przez myśl, ale wydaje się, że robię coś, co byłoby lepiej poradzone przez dołączenie do procedury przechowywanej. Ale może to jest więcej OO? :) –

+0

@Peter, powinieneś zrobić filtrowanie danych na poziomie bazy danych. Możesz przekazać New.GetAllNews (usersConcerned) i obsłużyć tablicę w swoim proc. Może to znacznie zmniejszyć natężenie ruchu sieciowego w zależności od danych. –

Powiązane problemy