Frage

I Programmierung in C # gerade erst begonnen und lese über Ihre Anwendung / Website in die drei verschiedenen Schichten Teilung wurde die beste Übung, aber ich habe eine harte Zeit zu verstehen, wie genau. Im arbeitet an einem Lieblingsprojekt mehr über C # lehnen, aber ich möchte nicht auf irgendwelchen schlechten Gewohnheiten starten. Können Sie sehen, was ich habe, und sehen, ob ich das richtig mache? Bieten einige Hinweise Vorschläge, wie alles zu brechen, um die verschiedenen Schichten?

Presentation Layer

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>Project: Ruth</title>
  <link href="CSS/StyleSheet.css" rel="stylesheet" type="text/css" />
</head>
<body>
  <form id="form1" runat="server">
    <div class="Body">
      <div class="Header">
        <div class="Nav">
          <img src="images/Header_Main.gif" alt="" width="217" height="101" />
          <div class="Menu">
            <a href="Default.aspx">
              <img src="images/Header_Home-Off.gif" alt="" /></a>
            <a href="Default.aspx">
              <img src="images/Header_About-Off.gif" alt="" /></a>
            <a href="Register.aspx">
              <img src="images/Header_Register-Off.gif" alt="" /></a>
            <a href="Default.aspx">
              <img src="images/Header_Credits-Off.gif" alt="" /></a>
          </div>
        </div>
      </div>
      <div class="Content">
        <div class="CurrentlyListening">
          <asp:Label ID="lblCurrentListen" runat="server" Text="(Nothing Now)" CssClass="Txt"></asp:Label>
        </div>
        <asp:GridView ID="gvLibrary" runat="server" AutoGenerateColumns="False" DataKeyNames="lib_id" DataSourceID="sdsLibrary" EmptyDataText="There are no data records to display." Width="760" GridLines="None">
          <RowStyle CssClass="RowStyle" />
          <AlternatingRowStyle CssClass="AltRowStyle" />
          <HeaderStyle CssClass="HeaderStyle" />
          <Columns>
            <asp:BoundField DataField="artist_name" HeaderText="Artist" SortExpression="artist_name" HeaderStyle-Width="200" />
            <asp:BoundField DataField="album_title" HeaderText="Album" SortExpression="album_title" HeaderStyle-Width="200" />
            <asp:BoundField DataField="song_title" HeaderText="Track" SortExpression="song_title" HeaderStyle-Width="200" />
            <asp:TemplateField HeaderText="DL">
              <ItemTemplate>
                <a href="http://####/Proj_Ruth/Data/<%# Eval("file_path") %>" class="lnk">Link</a>
              </ItemTemplate>
            </asp:TemplateField>
          </Columns>
        </asp:GridView>
        <asp:SqlDataSource ID="sdsLibrary" runat="server" ConnectionString="<%$ ConnectionStrings:MusicLibraryConnectionString %>" DeleteCommand="DELETE FROM [Library] WHERE [lib_id] = @lib_id" InsertCommand="INSERT INTO [Library] ([artist_name], [album_title], [song_title], [file_path]) VALUES (@artist_name, @album_title, @song_title, @file_path)" ProviderName="<%$ ConnectionStrings:MusicLibraryConnectionString.ProviderName %>" SelectCommand="SELECT [lib_id], [artist_name], [album_title], [song_title], [file_path] FROM [Library] ORDER BY [artist_name], [album_title]" UpdateCommand="UPDATE [Library] SET [artist_name] = @artist_name, [album_title] = @album_title, [song_title] = @song_title, [file_path] = @file_path WHERE [lib_id] = @lib_id">
          <DeleteParameters>
            <asp:Parameter Name="lib_id" Type="Int32" />
          </DeleteParameters>
          <InsertParameters>
            <asp:Parameter Name="artist_name" Type="String" />
            <asp:Parameter Name="album_title" Type="String" />
            <asp:Parameter Name="song_title" Type="String" />
            <asp:Parameter Name="file_path" Type="String" />
          </InsertParameters>
          <UpdateParameters>
            <asp:Parameter Name="artist_name" Type="String" />
            <asp:Parameter Name="album_title" Type="String" />
            <asp:Parameter Name="song_title" Type="String" />
            <asp:Parameter Name="file_path" Type="String" />
            <asp:Parameter Name="lib_id" Type="Int32" />
          </UpdateParameters>
        </asp:SqlDataSource>
      </div>
    </div>
  </form>
</body>
</html>

Business Layer

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

public class User
{
  DA da = new DA();

  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string EmailAddress { get; set; }
  public string Password { get; set; }
  public string AccessCode { get; set; }

  public User(string firstName, string lastName, string emailAddress, string password, string accessCode)
  {
    FirstName = firstName;
    LastName = lastName;
    EmailAddress = emailAddress;
    Password = password;
    AccessCode = accessCode;
  }

  public void CreateUser(User newUser)
  {
    if (da.IsValidAccessCode(newUser.AccessCode))
    {
      da.CreateUser(newUser);
    }
  }
}

Data Access Layer (DAL)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlTypes;
using System.Data.SqlClient;
using System.Configuration;

public class DA
{
  public DA()
  {
  }

  public bool IsValidAccessCode(string accessCode)
  {
    bool isValid = false;
    int count = 0;

    using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MusicLibraryConnectionString"].ConnectionString))
    {
      sqlCnn.Open();
      using (SqlCommand sqlCmd = new SqlCommand(String.Format("SELECT COUNT(*) FROM [AccessCodes] WHERE [accessCode_accessCode] = '{0}';", accessCode), sqlCnn))
      {
        count = (int)sqlCmd.ExecuteScalar();
        if (count == 1)
        {
          isValid = true;
        }
      }
    }
    return isValid;
  }

  public void CreateUser(User newUser)
  {
    using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MusicLibraryConnectionString"].ConnectionString))
    {
      sqlCnn.Open();
      using (SqlCommand sqlCmd = new SqlCommand(String.Format("INSERT INTO [Users] (user_firstName, user_lastName, user_emailAddress, user_password, user_accessCode) VALUES ('{0}', '{1}', '{2}', '{3}', '{4}');", newUser.FirstName, newUser.LastName, newUser.EmailAddress, newUser.Password, newUser.AccessCode), sqlCnn))
      {
        sqlCmd.ExecuteNonQuery();
      }
    }
    DeleteAccessCode(newUser.AccessCode);
  }

  public void DeleteAccessCode(string accessCode)
  {
    using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MusicLibraryConnectionString"].ConnectionString))
    {
      sqlCnn.Open();
      using (SqlCommand sqlCmd = new SqlCommand(String.Format("DELETE FROM [AccessCodes] WHERE [accessCode_accessCode] = '{0}';", accessCode), sqlCnn))
      {
        sqlCmd.ExecuteNonQuery();
      }
    }
  }
}
War es hilfreich?

Lösung

Jon,

Eines der ersten Dinge zu verstehen, dass, wenn Sie beabsichtigen, Schicht-basierten Anwendungen zu bauen, dann sollten Sie nicht SQL-Anweisungen direkt in ASPX-Seiten werden Speicher (wie die SqlDataSource erfordert). Die SqlDataSource Kontrolle wurde zu demonstrieren gebaut, wie einfach es ist, eine Anwendung mit Datenbankdaten zu binden und zu aktualisieren und nicht in realen Anwendungen verwendet werden sollte, weil es besiegt irgendwie den Zweck, eine BL-Schicht und Datalayer zu haben, wenn Sie gehen zu Wählen Sie speichern / Aktualisieren / löschen / Insert-Anweisungen in der ASPX-Seite.

Der ganze Zweck der Schicht-basierten Anwendungsdesign ist jede Schicht zu verkapseln, so dass es keine Kreuzung. Jede Schicht in Wechselwirkung mit der öffentlichen Schnittstelle der anderen Schichten und weiß nichts über ihre interne Implementierung.

Die gangbare Alternative ist es daher, die ObjectDataSource Steuerung zu verwenden. Diese Steuerung ermöglicht es Ihnen, direkt an ein Datalayer oder zu einer Biz-Logik-Schicht, die wiederum zu binden, kann data nennen. Die Bindung an ein Datalayer hat direkt den Nachteil, dass Sie Datenstrukturen zurückkehren, die das Schema der Datenbanktabellen aussetzen (zum Beispiel Tables oder Dataviews).

So ist der empfohlene Fluss der Logik wie folgt:

Die ASPX-Seite verwendet ein Datasource-Steuerelement zu einer BL-Klasse zu binden. Diese BL-Klasse bietet entsprechende Funktionen wie GetData, UpdateData, DeleteData and InsertData (mit allen erforderlichen Überlastungen), und diese Funktionen geben stark typisierte Objekte oder Sammlungen, die die ObjectDataSource mit und Display arbeiten. Jede öffentliche Funktion in der BL-Klasse ruft intern in die Datalayer auszuwählen / update / delete / insert Daten in / aus der Datenbank.

Eine ausgezeichnete Einführung in diese Schicht basierten Design in ASP.NET wird in dem Quickstarts

P. S : @Andy genannten Generika datalayers, die mit allen Szenarien arbeiten. Siehe diese Frage für ein Beispiel dessen, was es aussehen würde.

Andere Tipps

Die größte Erklärung von logischen Schichten in ASP.NET-Anwendungen stammt aus zwei Quellen. Die erste ist die Microsoft-eigenen ASP.NET-Website geschrieben von Scott Mitchell es auf die Trennung von Logik eine gute Einführung bietet. Die Tutorials sind recht wortreich, aber ich fand sie sehr nützlich. Die URL ist http://www.asp.net/learn/data-access/.

Die zweite Ressource, die ich sehr nützlich fand aus, dass gefolgt auf und es wurde geschrieben von Imar Spaanjaars und ist hier . Es ist ein viel technischer Artikel, sondern bietet eine gute Möglichkeit, um die Struktur zu Ihrer Anwendung hinzuzufügen.

Ich hoffe, das hilft.

Ian.

Wenn Sie Ihren Code schreiben letztlich tragbar sein, werden Sie feststellen, werden Sie 3 (oder mehr!) Schichten in Ihrer Anwendung.

Zum Beispiel - stattdessen Ihre Data Access Layer Arbeit speziell für diese Anwendung zu machen, es schreiben, so dass Sie nie wieder zu schreiben. Stellen Sie sicher, dass alle Funktionen Variablen übergeben werden können, und Sie verlassen sich nicht auf globale Variablen (oder so wenig wie möglich). Wenn es Zeit für Ihr nächstes Projekt kommt -. Kopieren und Ihre DAL einfügen und plötzlich bist du wieder läuft

Und es ist noch nicht alles - Sie könnten eine Unterschicht für Ihre DAL schreiben wollen, die zwischen MySQL und MSSQL (nur als Beispiel) interpretiert. Oder Sie könnten eine Bibliothek von gemeinsamen Funktionen, die Sie, wie Text sanitären Einrichtungen oder CSS Generation oder etwas auszuführen.

Wenn Sie Ihren Code schreiben, so dass eines Tages Sie sich hinsetzen, eine App zu schreiben - und es geht meist Ausschneiden und Einfügen vorherigen Code - Sie haben erreicht Programmierer Nirwana. :)

Die ganze Idee hinter einer Anwendung Schichtung ist, dass jede Schicht hängt nicht von Implementierungsdetails der Schicht (en) unten. Zum Beispiel in Ihrem Code haben Sie eine T-SQL-Anweisung in Ihrer Präsentationsschicht. Dies bedeutet, dass Sie eine direkte Abhängigkeit von Ihrer Präsentationsschicht auf Ihrer Datenbank (die untere Schicht). Wenn Sie eine Änderung in Ihrer Datenbank vornehmen, müssen Sie auch eine Änderung in der Präsentationsschicht machen. Im Idealfall ist dies nicht das, was Sie wollen. Die Präsentationsschicht sollte nur besorgt über Daten zu präsentieren, nicht darüber, wie es abzurufen. Angenommen, Sie Ihre ganze Datenbank in CSV-Dateien verschieben (ich weiß, verrückte Idee), dann sollten Sie Ihre Präsentationsschicht nicht bewusst sein, auf all dies.

Am besten, haben Sie eine Business-Schicht-Methode, die nur die Daten, die Sie für den Benutzer angezeigt werden sollen zurückgibt. Sie sollten einen Blick auf ObjectDataSource statt SqlDataSource. SqlDataSource ist schön für kleine Prototyping-Projekte, aber man sollte es nicht für ernstere Projekte verwendet werden.

Zwischen Business-Schicht und Datenschicht sollten Sie eine ähnliche Trennung haben. Die Datenschicht ist verantwortlich für das Erhalten der Daten, die Sie von einem Speicherort (Datenbank, CSV-Datei, Web Service, ...) werden sollen. Auch hier, im Idealfall sollte die Business-Schicht nicht auf die Details der Implementierung der Datenschicht abhängen. Wenn Sie SQL Server zum Beispiel sprechen, sollten Sie nicht zurückgeben SqlDataReader Beispiel auf Ihre Business-Schicht. Dadurch verhindern Sie eine Abhängigkeit von Ihrer Business-Schicht auf einer Implementierung Detail Ihrer Datenschicht erstellen:. Die eigentliche Datenbank es es Daten aus abruft

In der Praxis sehen Sie, dass die Business-Schicht auf Details der Implementierung der Datenschicht abhängt in einer oder anderen Weise und in der Regel, das ist keine schlechte Sache. Wann war das letzte Mal, wenn Sie entschieden Datenbanken zu wechseln? Aber Abhängigkeiten zu beseitigen und Implementierungsdetails so viel wie möglich zu isolieren fast immer zu einer Anwendung, die einfacher zu pflegen und zu verstehen.

Sie können eine ähnliche Erklärung finden hier .

als Seite, um die Hauptstoßrichtung seiner Frage, würde ich Ihnen empfehlen bei ASPNET_REGSQL suchen, um Ihre SQL-Datenbank zu konfigurieren Fähigkeiten zu handhaben .Net-internen Mitgliedschaft / profile / Rolle. Es wäre für die Erstellung / Aktualisierung Benutzer viel Shag und Ärger zu entfernen, etc. Ich nicht Profil eine ganze Menge verwendet haben, aber es ermöglicht es Ihnen, „tack auf“ zusätzliche Attribute zu Ihrem Benutzer, zum Beispiel Access.

Wenn Sie mit einer bestehenden DB-Struktur zu tun hat, die bereits tut Benutzerauthentifizierung etc. Sie einen benutzerdefinierten Mitgliedschaft Anbieter schaffen könnten, die die bestehenden DB-Tabellen und Stored Procedures nutzen würde.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top