8 Stimmen

Präsentation, Geschäfts- und Datenebene

Ich habe gerade angefangen, in C# zu programmieren, und habe gelesen, dass das Unterteilen Ihrer Anwendung / Website in die drei verschiedenen Ebenen bewährte Praxis war, aber ich habe Schwierigkeiten zu verstehen, wie genau das funktioniert. Ich arbeite an einem eigenen Projekt, um mehr über C# zu erfahren, aber ich möchte keine schlechten Gewohnheiten entwickeln. Können Sie bitte sehen, was ich habe und prüfen, ob ich das richtig mache? Bieten Sie einige Hinweise und Vorschläge, wie Sie alles in die verschiedenen Ebenen unterteilen können?

Präsentationsschicht

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

  Projekt: Ruth

                " class="lnk">Link

Geschäftsschicht

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

Datenzugriffsschicht (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();
      }
    }
  }
}

9voto

Cerebrus Punkte 25410

Jon,

Eines der ersten Dinge zu verstehen ist, dass wenn Sie schichtbasierte Anwendungen erstellen möchten, sollten Sie keine SQL-Anweisungen direkt innerhalb von ASPX-Seiten speichern (wie es der SqlDataSource erfordert). Die SqlDataSource-Steuerung wurde gebaut, um zu zeigen, wie einfach es ist, eine Anwendung mit Datenbankdaten zu verbinden und zu aktualisieren, und ist nicht dafür gedacht, in Echtweltanwendungen verwendet zu werden, da es irgendwie den Sinn einer BL-Schicht und Datalayer zunichte macht, wenn Sie Select/Update/Delete/Insert-Anweisungen in der ASPX-Seite speichern.

Der gesamte Zweck des Designs layerbasierter Anwendungen besteht darin, jede Schicht so zu kapseln, dass es keine Überschneidungen gibt. Jede Schicht interagiert mit der öffentlichen Schnittstelle der anderen Schichten und weiß nichts über deren interne Implementierung.

Die empfehlenswerte Alternative ist daher die Verwendung der ObjectDataSource-Steuerung. Diese Steuerung ermöglicht es Ihnen, direkt an eine DataLayer oder an eine Biz-Logikschicht zu binden, die wiederum die DataLayer aufrufen kann. Das Binden an eine DataLayer direkt hat den Nachteil, dass Sie Datenstrukturen zurückgeben werden, die das Schema der Datenbanktabellen offenlegen (z.B. DataTables oder DataViews).

Also ist der empfohlene Logikablauf wie folgt:

Die ASPX-Seite verwendet eine DataSource-Steuerung, um an eine BL-Klasse zu binden. Diese BL-Klasse bietet geeignete Funktionen wie GetData, UpdateData, DeleteData und InsertData (mit erforderlichen Überladungen) und diese Funktionen geben stark typisierte Objekte oder Sammlungen zurück, mit denen die ObjectDataSource arbeiten und anzeigen kann. Jede öffentliche Funktion in der BL-Klasse ruft intern die DataLayer auf, um Daten aus der Datenbank auszuwählen/zu aktualisieren/zu löschen/einzufügen.

Eine ausgezeichnete Einführung in dieses schichtbasierte Design in ASP.NET finden Sie in den Quickstarts

N.B.: @Andy erwähnte generische Datalayer, die mit allen Szenarien funktionieren. Sehen Sie sich diese Frage an, um zu sehen, wie es aussehen könnte.

3voto

Ian Roke Punkte 1724

Die beste Erklärung für Logikschichten in ASP.NET-Anwendungen stammt aus zwei Quellen. Die erste stammt von der ASP.NET-Website von Microsoft, verfasst von Scott Mitchell, und bietet eine gute Einführung in die Trennung der Logik. Die Tutorials sind ziemlich langatmig, aber ich fand sie sehr nützlich. Die URL lautet http://www.asp.net/learn/data-access/.

Die zweite Ressource, die ich sehr hilfreich fand, baut darauf auf und wurde von Imar Spaanjaars verfasst und ist hier verfügbar. Es handelt sich um einen viel technischeren Artikel, der jedoch eine großartige Methode bietet, um die Struktur Ihrer Anwendung hinzuzufügen.

Ich hoffe, das hilft.

Ian.

0voto

Andy Moore Punkte 865

Wenn Sie Ihren Code letztendlich portabel schreiben, werden Sie feststellen, dass Sie 3 (oder mehr!) Ebenen in Ihrer Anwendung haben.

Zum Beispiel - anstatt Ihre Data Access Layer speziell für diese eine Anwendung zu entwickeln, schreiben Sie diese so, dass Sie sie nie wieder schreiben müssen. Stellen Sie sicher, dass alle Ihre Funktionen Variablen übergeben werden können und Sie sich nicht auf globale Variablen verlassen (oder so wenig wie möglich). Wenn es Zeit für Ihr nächstes Projekt ist - kopieren und fügen Sie Ihren DAL ein und plötzlich sind Sie wieder einsatzbereit.

Und damit ist es noch nicht vorbei - Sie möchten vielleicht eine Subebene für Ihren DAL schreiben, die zwischen MySQL und MSSQL vermittelt (nur als Beispiel). Oder Sie haben eine Bibliothek mit gemeinsamen Funktionen, die Sie ausführen, wie z. B. Textsäuberung oder CSS-Generierung oder so etwas.

Wenn Sie Ihren Code so schreiben, dass Sie eines Tages hinsetzen, um eine App zu schreiben - und es größtenteils darum geht, früheren Code zu kopieren und einzufügen - dann haben Sie Programmierernirwana erreicht. :)

0voto

Ronald Wildenberg Punkte 30961

Die ganze Idee hinter der Schichtung einer Anwendung besteht darin, dass jede Schicht nicht auf Implementierungsdetails der darunterliegenden Schicht(en) angewiesen ist. Zum Beispiel haben Sie in Ihrem Code eine T-SQL-Anweisung innerhalb Ihrer Präsentationsschicht. Das bedeutet, dass Ihre Präsentationsschicht direkt von Ihrer Datenbank (der untersten Schicht) abhängig ist. Wenn Sie eine Änderung in Ihrer Datenbank vornehmen, müssen Sie auch eine Änderung in Ihrer Präsentationsschicht vornehmen. Idealerweise ist das nicht das, was Sie wollen. Die Präsentationsschicht sollte sich nur darum kümmern, Daten zu präsentieren, nicht darum, wie sie abgerufen werden. Nehmen wir an, Sie verschieben Ihre gesamte Datenbank in CSV-Dateien (ich weiß, verrückte Idee), dann sollte Ihre Präsentationsschicht davon überhaupt nichts wissen.

Also idealerweise haben Sie eine Methode in der Business-Schicht, die nur die Daten zurückgibt, die Sie dem Benutzer anzeigen möchten. Sie sollten sich ObjectDataSource ansehen, anstelle von SqlDataSource. SqlDataSource ist gut für kleine Prototypenprojekte, aber Sie sollten es nicht für ernstere Projekte verwenden.

Zwischen Business-Schicht und Daten-Schicht sollten Sie eine ähnliche Trennung haben. Die Daten-Schicht ist dafür verantwortlich, die Daten, die Sie von einem Speicherort (Datenbank, CSV-Datei, Webdienst, ...) möchten, abzurufen. Auch hier sollte idealerweise die Business-Schicht nicht von den Implementierungsdetails der Daten-Schicht abhängen. Wenn Sie zum Beispiel mit SQL Server sprechen, sollten Sie Ihrer Business-Schicht keine SqlDataReader-Instanz zurückgeben. Wenn Sie dies tun, schaffen Sie eine Abhängigkeit Ihrer Business-Schicht von einem Implementierungsdetail Ihrer Daten-Schicht: der tatsächlichen Datenbank, von der sie ihre Daten abruft.

In der Praxis hängt die Business-Schicht in irgendeiner Weise von Implementierungsdetails der Daten-Schicht ab, und das ist normalerweise nicht schlecht. Wann haben Sie das letzte Mal beschlossen, Datenbanken zu wechseln? Aber das Vermeiden von Abhängigkeiten und das Isolieren von Implementierungsdetails so weit wie möglich führen fast immer zu einer Anwendung, die einfacher zu warten und zu verstehen ist.

Eine ähnliche Erklärung finden Sie hier.

0voto

Mike Kingscott Punkte 477

Als eine Anmerkung zur Hauptfrage würde ich empfehlen, ASPNET_REGSQL zu verwenden, um Ihre SQL-Datenbank zu konfigurieren, um die integrierten Mitgliedschafts-/Profil-/Rollenfunktionen von .Net zu verarbeiten. Es würde viel Aufwand ersparen, Benutzer zu erstellen/zu aktualisieren, etc. Ich habe das Profil nicht viel benutzt, aber es ermöglicht es Ihnen, zusätzliche Attribute an Ihren Benutzer anzuhängen, z.B. Zugriffscode.

Wenn Sie mit einer bestehenden DB-Struktur arbeiten, die bereits die Benutzerauthentifizierung usw. durchführt, könnten Sie einen benutzerdefinierten Mitgliedschaftsanbieter erstellen, der auf die vorhandenen DB-Tabellen und gespeicherten Prozeduren zurückgreifen würde.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X