我刚开始编程在C#和阅读有关的分割你的应用程序/网站进入的三个不同层是最好的做法,但我有一个很难确切了解如何。Im工作在一个宠物项目,贫更多关于C#但我不想要开始上任何不良的习惯。你可以看看我,看看如果我这样做吗?提供一些提示,建议如何打破一切到不同层?

介绍层

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

业务层

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

数据存取层(达尔)

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();
      }
    }
  }
}
有帮助吗?

解决方案

乔,

首先要理解的是,如果您打算构建基于图层的应用程序,那么您不应该直接在ASPX页面中存储SQL语句(如 SqlDataSource 所要求的那样)。构建 SqlDataSource 控件是为了演示使用数据库数据绑定和更新应用程序是多么容易,并且不打算在现实世界的应用程序中使用,因为它有点破坏了拥有BL层的目的如果要在ASPX页面中存储选择/更新/删除/插入语句,则使用Datalayer。

基于图层的应用程序设计的全部目的是封装每个层,以便没有交集。每个层都与其他层的公共接口交互,并且对其内部实现一无所知。

因此,可行的替代方法是使用 ObjectDataSource 控件。此控件允许您直接绑定到DataLayer或Biz逻辑层,而Biz逻辑层又可以调用Datalayer。直接绑定到Datalayer的缺点是,您将返回公开数据库表模式的数据结构(例如,DataTables或DataViews)。

因此,推荐的逻辑流程如下:

ASPX页面使用DataSource控件绑定到BL类。 这个BL类提供了适当的函数,比如 GetData,UpdateData,DeleteData和InsertData (带有任何必需的重载),这些函数返回 ObjectDataSource 可以使用的强类型对象或集合。和显示。 BL类中的每个公共函数都在内部调用DataLayer来选择/更新/删除/插入数据库中的数据。

快速入门

P.S :@Andy提到了适用于所有方案的通用数据层。请参阅此问题,了解其中的一个示例看起来像。

其他提示

ASP.NET应用程序中逻辑层的最佳解释来自两个来源。第一个是由Scott Mitchell编写的微软自己的ASP.NET网站,它提供了对逻辑分离的良好介绍。这些教程非常冗长,但我发现它们非常有用。该网址为 http://www.asp.net/learn/data-access/

我发现第二个资源非常有用,它是由Imar Spaanjaars编写的,可用这里。这是一篇技术性更强的文章,但提供了一种将结构添加到应用程序的好方法。

我希望有所帮助。

伊恩。

如果你编写的代码最终是可移植的,你会发现你的应用程序中有3层(或更多层)。

例如 - 不要让您的数据访问层专门针对这个应用程序工作,而是编写它以便您永远不必再次编写它。确保所有函数都可以传递变量,并且不依赖于全局变量(或尽可能少)。到了下一个项目的时候 - 复制并粘贴你的DAL,突然你又开始运行了。

它并没有结束 - 您可能想要为DAL编写一个子层,用于解释MySQL和MSSQL之间的区域(仅作为示例)。或者您可能拥有一个常用功能库,例如文本卫生或CSS生成等。

如果您编写代码以便有一天,您坐下来编写应用程序 - 而且主要涉及剪切和粘贴以前的代码 - 您已经达到了程序员的必杀技。 :)

整个想法背后的分层应用程序是每个层并不取决于执行的细节层(s)下。例如,在你的代码中有一个T-SQL statement在你的演讲层。这意味着你有一个直接依赖性的演讲层在你的数据库(在底层)。如果你改变你的数据库,还必须做出改变,在你介绍层。理想的是这不是你想要什么。表示层应只关注数据呈现,没有关如何检索它。假设你移动你的整个数据库进CSV文件(我知道,疯狂的想法),那么你的演讲层不应该知道这个在所有。

所以理想的是,你有一个业务层的方法,回返只是你想要的数据,以显示用户使用。你应该看看 ObjectDataSource 而不是的 SqlDataSource. SqlDataSource 是很好的小型原型项目,但不应将其用于任何更严重的项目。

之间的业务层和数据层,你应该有一个类似的分离。数据层负责得到你想要的数据从一些存储位置(数据库、CSV文件,网络服务,...).再次,理想的情况是,业务层不应取决于执行的细节的数据层。如果你在说到SQL服务器例如,你不应该返回 SqlDataReader 实例来你业务层。通过这样做,你创建的一个依赖性的业务层在实施有详细的数据层:实际的数据库检索的数据。

在实践中可以看到,业务层不会取决于执行的细节的数据层中的某种方式或另一种,通常这不是一件坏事。当最后一次你决定开关的数据库?但是,消除的依赖和孤立的执行情况的详细信息尽可能多的几乎总是导致在一个应用程序,更容易维持和理解。

你可以找到一个类似的解释 在这里,.

除了他的问题的主旨之外,我建议你看看ASPNET_REGSQL来配置你的SQL数据库来处理.Net的内置成员/配置文件/角色能力。它会消除很多粗略和麻烦的创建/更新用户等。我没有使用配置文件非常多,但它允许你“粘贴”您的用户的额外属性,例如AccessCode。

如果您正在处理已经进行用户身份验证等的现有数据库结构,则可以创建一个自定义成员资格提供程序,该提供程序将利用现有的数据库表和存储过程。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top