2009-11-04 4 views
7

Ich kämpfe mit der Überbrückung der Konzepte von gutem Datenbankdesign mit gutem objektorientiertem Design.Rückgabe von Daten aus der Datenbank in .net: Rückgabe eines DataTable oder LIst <T>?

Traditionell wenn ich eine Liste von Nachrichten in einem Repeater angezeigt werden wollte, würde ich so etwas wie:

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

Hier News.GetAllNews() gibt ein Datatable, das nur ein dump von was die gespeicherte Prozedur zurückgibt. Die gespeicherte Prozedur wird geschrieben, um Daten mithilfe von Joins zurückzugeben, sodass mehr als eine Tabelle Daten enthält.

Dies hat den Vorteil, dass in der Datenbank die gespeicherte Prozedur nachschlagen können, die die Nachrichten Geschichte aus dem AddedByID hinzugefügt, die Nachrichten Tabelle existiert in der und geben die Personen vollständigen Namen als AddedByFullName Wert zurückgegeben .

Allerdings, wenn ich die Verwendung eines Datatable versuchen und fallen und stattdessen eine Liste der Nachrichten Objekte zurück, erhalte ich folgendes:

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

Aber jetzt mit dem Problem, das ich bin gelassen, dass bestimmte Werte, die Ich möchte (wie AddedByFullName) nicht in dem News-Objekt vorhanden sein, da sie nicht explizit festgelegt sind, sondern von einer Nachschlag-ID in dem Objekt abgerufen werden.

Ich möchte Objekte lieber als DataTables zurückgeben, aber ich kenne nicht den besten Weg, diese Lücke zu überbrücken.

Do I:
* Erstellen Sie zusätzliche Eigenschaften in der Nachrichten Klasse für jeden zusätzlichen Wert, der aus der Datenbank in Bezug auf diese Daten zurückgeführt werden kann?
* Stick mit DataTables für bestimmte Fälle, wo das viele zusätzliche Werte sind?

Oder bin ich einfach total auf dem Holzweg!

Antwort

4

Ihre Entscheidungen durch die zugrunde liegende Technologie beschränkt sind Sie bereit sind, als den Datenzugriff zu verwenden. Im Moment gibt es mehrere Alternativen, die das VS Toolset und .Net Framework unterstützt:

  • Classic ADO.Net 2.0. Design in Typed datasets und DataTable Objekte in Code.
  • LINQ to SQL. Design in LINQ O/R Design modeler, verwenden Sie IQueryable<T> und LINQ-Syntax in Code.
  • Entity Framework. Entwerfen Sie in der Entity Data modeler Entitäten in Ihrem Code.
  • 3rd-Party-ORM-Tools wie NHibernate. Jeder hat seinen eigenen spezifischen Designer- und Code-Objekttyp.
  • Von diesen, alle außer ADO.Net typisierte Datensätze können Sie Navigationsbeziehungen angeben, wie Sie fragen, entweder eifrig oder faul geladen. In einem Fall, wie Sie es beschreiben, würde das natürliche Vorgehen mit diesen Technologien darin bestehen, die Beziehung zwischen News-Artikel und Autor explizit in den Designern zu modellieren und das Framework mit dem Problem des Ladens der entsprechenden Daten und in die entsprechenden Typen, letztlich auch der Bedeutung, zu befassen Das Join-Problem wird implizit von der Anwendungsdatenzugriffsebene (dem Framework) und nicht von einer explizit erstellten gespeicherten Prozedur behandelt.

    Die Wahl der Technologie wird überall in Ihrem Code, von wie Sie Ihre Daten abrufen, wie Sie es anzeigen und wie Sie aktualisieren, keine dieser Technologien sind leicht austauschbar. Persönlich finde ich, dass LINQ to SQL das richtige Gleichgewicht von Macht und Komplexität darstellt.

    +0

    Vielen Dank für Ihre Eingabe Remus - Ich habe gehört, dass MS die Entwicklung von LINQ to SQL zugunsten des Entity Framework gestoppt hat. Stimmt das und wenn ja, würden Sie neue Entwicklungen mit dieser Technologie fördern? –

    +0

    @Peter: Ich bin nicht mehr mit MS, also würde ich nicht wirklich mehr wissen als ist öffentlich bekannt. Es stimmt, dass EF in der Zukunft der empfohlene Weg ist, aber angesichts der überwältigenden Akzeptanz von LINQ to SQL im Vergleich zu EF würde ich davon absehen, es komplett aufgegeben zu sehen. –

    +0

    Ich benutze und genieße LINQ2SQL für ein .net 3.5 Projekt. Mein nächstes großes Projekt wird .net 4.0 verwenden, also werde ich das Entity Framework 4.0 verwenden –

    0

    Gute Frage:

    Es gibt ein paar Ansätze, die Sie ergreifen können:

    1. Sie können die zusätzlichen Daten abrufen, die Sie auf dem Bindungsereignis des Repeaters müssen und füllen es in eine " Platzhalter "für jede Nachricht, die zurückgegeben wird. Dies führt zu Leistungsproblemen aufgrund der zusätzlichen Abfrage, aber es funktioniert.

    2. Wenn möglich, würde ich das Nachrichtenobjekt ändern, um die zusätzlichen Informationen zu enthalten, oder ein Objekt erstellen, das von dem Nachrichtenobjekt erbt, das die zusätzlichen Informationen oder Eigenschaften enthielt.

    hoffte, das hilft :-) +1

    Bearbeiten/Kommentar: ich denke, die Reibung Sie in Ihrem Design sieht, ist, dass Sie nicht das honorieren „hat-eine“ Beziehung zwischen Ihrem Nachrichtenobjekt und was ich seinen Autor/Mitwirkenden nennen würde.Der Join, den Sie in Ihrer Abfrage ausführen, verschleiert lediglich das Fehlen der Beziehung im Objektmodell.

    +0

    Danke für den Eingang Achilles: 1) Ähnlich wie Gregoire Vorschlag. Wie Sie sagen, es wird die Arbeit machen, aber diese Art von Ansatz scheint nur wie eine zusätzliche Arbeit? 2) Ich weiß, das wird effizienter sein, aber es fühlt sich immer noch ein wenig spikey ... obwohl ich es über Option 1 bevorzuge Ich hoffe ich für einen Vorschlag, der sich richtig anfühlt, wo diese Ansätze nicht tun fühle mich wie eine perfekte Passform. –

    +0

    Ich glaube, die Reibung, die Sie in Ihrem Design sehen, ist, dass Sie nicht die "has-a" -Beziehung zwischen Ihrem Nachrichtenobjekt und dem, was ich seinen Autor/Mitwirkenden nennen würde, anerkennen. Der Join, den Sie in Ihrer Abfrage ausführen, verschleiert lediglich das Fehlen der Beziehung im Objektmodell. – Achilles

    +0

    Guter Punkt, gut gemacht –

    0

    Sie können dies versuchen, vielleicht nicht die bessere Lösung:

    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

    Diese Art von Ansatz kam mir in den Sinn, aber es scheint etwas zu tun, das besser durch eine Join in einer gespeicherten Prozedur behandelt werden würde. Aber dann ist das vielleicht mehr OO? :) –

    +0

    @Peter, sollten Sie die Datenfilterung auf Datenbankebene tun. Sie könnten New.GetAllNews (usersConcerned) übergeben und das Array in Ihrem Prozess behandeln. Dies könnte den Umfang des Netzwerkverkehrs abhängig von Ihren Daten drastisch reduzieren. –

    Verwandte Themen