3-х уровневая архитектура - нужен пример - PullRequest
13 голосов
/ 06 января 2010

В настоящее время я работаю с использованием одноуровневой архитектуры. Теперь я хочу научиться писать код с использованием трехуровневой архитектуры. Пожалуйста, не могли бы вы привести простой пример?

Ответы [ 9 ]

22 голосов
/ 06 января 2010

В Википедии есть хорошее объяснение: Многоуровневая архитектура :

«Трехуровневая» - это клиент-серверная архитектура, в которой пользовательский интерфейс, функциональная логика процесса («бизнес-правила»), компьютерное хранилище данных и доступ к данным разрабатываются и поддерживаются как независимые модули, чаще всего на отдельных платформах.

alt text

Использование веб-разработки

В области веб-разработки трехуровневый часто используется для ссылки на веб-сайты, обычно сайты электронной коммерции, которые создаются с использованием трех уровней:

  • Интерфейсный веб-сервер, обслуживающий статический контент и, возможно, некоторый кэшированный динамический контент.
  • Сервер приложений среднего уровня обработки контента и уровня генерации, например Java EE, ASP.net, платформа PHP.
  • Внутренняя база данных, содержащая как наборы данных, так и систему управления базой данных или программное обеспечение СУБД, которое управляет данными и обеспечивает доступ к ним.
15 голосов
/ 06 января 2010

Это то, что у меня есть в моем проекте. Больше, чем просто традиционная 3-уровневая архитектура.

1.) Application.Infrastructure

  • Базовые классы для всех бизнес-объектов, коллекции бизнес-объектов, классы доступа к данным и мои пользовательские атрибуты и утилиты в качестве методов расширения, общая структура проверки. Это определяет общую организацию поведения моего окончательного приложения .net.

2.) Application.DataModel

  • Типизированный набор данных для базы данных.
  • Адаптеры таблиц расширены для включения транзакций и других функций, которые могут мне понадобиться.

3.) Application.DataAccess

  • Классы доступа к данным.
  • Фактическое место, где действия базы данных запрашиваются с использованием базового набора типизированных данных.

4.) Application.DomainObjects

  • Бизнес-объекты и коллекции бизнес-объектов.
  • Перечисления.

5.) Application.BusinessLayer

  • Предоставляет классы менеджера, доступные на уровне презентации.
  • HttpHandlers.
  • Базовый класс моей собственной страницы.
  • Здесь все больше и больше ..

6.) Application.WebClient или Application.WindowsClient

  • Мой уровень презентации
  • Принимает ссылки из Application.BusinessLayer и Application.BusinessObjects.

Application.BusinessObjects используются во всем приложении и перемещаются по всем уровням, когда это необходимо [кроме Application.DataModel и Application.Infrastructure]

Все мои запросы определяются только Application.DataModel.

Application.DataAccess возвращает или принимает бизнес-объекты как часть любой операции доступа к данным. Бизнес-объекты создаются с помощью атрибутов отражения. Каждый бизнес-объект помечается сопоставлением атрибутов с целевой таблицей в базе данных, а свойства внутри бизнес-объекта помечаются сопоставлением атрибутов с целевым столбцом в соответствующей таблице базы данных.

Моя структура проверки позволяет мне проверять каждое поле с помощью назначенного атрибута Validation.

Моя фреймворк активно использует атрибуты для автоматизации большинства утомительных задач, таких как сопоставление и проверка. Я также могу добавить новую функцию в качестве нового аспекта в рамках.

Пример бизнес-объекта будет выглядеть в моем приложении следующим образом.

User.cs

[TableMapping("Users")]
public class User : EntityBase
{
    #region Constructor(s)
    public AppUser()
    {
        BookCollection = new BookCollection();
    }
    #endregion

    #region Properties

    #region Default Properties - Direct Field Mapping using DataFieldMappingAttribute

    private System.Int32 _UserId;

    private System.String _FirstName;
    private System.String _LastName;
    private System.String _UserName;
    private System.Boolean _IsActive;

    [DataFieldMapping("UserID")]
    [DataObjectFieldAttribute(true, true, false)]
    [NotNullOrEmpty(Message = "UserID From Users Table Is Required.")]
    public override int Id
    {
        get
        {
            return _UserId;
        }
        set
        {
            _UserId = value;
        }
    }

    [DataFieldMapping("UserName")]
    [Searchable]
    [NotNullOrEmpty(Message = "Username Is Required.")]
    public string UserName
    {
        get
        {
            return _UserName;
        }
        set
        {
            _UserName = value;
        }
    }

    [DataFieldMapping("FirstName")]
    [Searchable]
    public string FirstName
    {
        get
        {
            return _FirstName;
        }
        set
        {
            _FirstName = value;
        }
    }

    [DataFieldMapping("LastName")]
    [Searchable]
    public string LastName
    {
        get
        {
            return _LastName;
        }
        set
        {
            _LastName = value;
        }
    }

    [DataFieldMapping("IsActive")]
    public bool IsActive
    {
        get
        {
            return _IsActive;
        }
        set
        {
            _IsActive = value;
        }
    }

    #region One-To-Many Mappings
    public BookCollection Books { get; set; }

    #endregion

    #region Derived Properties
    public string FullName { get { return this.FirstName + " " + this.LastName; } }

    #endregion

    #endregion

    public override bool Validate()
    {
        bool baseValid = base.Validate();
        bool localValid = Books.Validate();
        return baseValid && localValid;
    }
}

BookCollection.cs

/// <summary>
/// The BookCollection class is designed to work with lists of instances of Book.
/// </summary>
public class BookCollection : EntityCollectionBase<Book>
{
    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection()
    {
    }

    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection (IList<Book> initialList)
        : base(initialList)
    {
    }
}
10 голосов
/ 06 января 2010

Под «уровнем» вы подразумеваете «слой» в программном стеке? Слово «уровень» лучше использовать для описания физических компонентов вашей системы. Если вы используете ASP.NET, у вас, вероятно, уже есть «трехуровневая» система -

  1. Браузер, отображающий веб-страницы
  2. IIS-сервер, на котором размещено ваше приложение
  3. Сервер базы данных с вашей базой данных

Но вы, возможно, помещаете весь свой код в один программный «слой» - в частности, код, стоящий за файлом ваших страниц aspx. Вы хотите перейти от одного слоя к подходу 3 слоя. Классическая «трехслойная» программная архитектура состоит из следующих элементов:

  1. Уровень представления

  2. Уровень бизнес-логики (BLL)

  3. Уровень доступа к данным (DAL)

alt text
(источник: asp.net )

Для типичного приложения ASP.NET вы можете применить это следующим образом. Сначала вы создаете файл LINQ2SQL (.dbml), содержащий объекты для доступа к вашей базе данных. Это ваш Уровень доступа к данным (DAL).

Затем вы можете создать библиотеку DLL, которая будет содержать ваш уровень бизнес-логики (BLL). Этот уровень будет обращаться к базе данных через DAL, манипулировать ею по мере необходимости, а затем предоставлять ее через простой интерфейс. Например, если ваше приложение отображает список клиентов, ваша BLL может иметь открытую функцию GetClientList (), которая возвращает список клиентов.

Наконец, вы должны настроить свой код за файлами, чтобы создать экземпляр BLL и подключить его к компонентам интерфейса. Это ваш Уровень представления . Например, он может взять данные, возвращенные из вашей функции GetClientList (), и связать их с сеткой данных в веб-форме. Идея состоит в том, чтобы сделать слой представления как можно более тонким.

Это кажется немного скучным, чтобы описать, но это довольно просто, как только вы сделали это пару раз. Вы обнаружите, что такое разделение вашего приложения значительно облегчит обслуживание, поскольку разделение проблем ведет к более чистому коду. Вам также будет намного проще обновить или даже заменить слой презентации, так как он содержит очень мало умов. Наконец, вы достигнете точки, где у вас есть ряд очень полезных библиотек BLL, которые вы можете легко использовать в новых приложениях, что значительно повышает производительность.

4 голосов
/ 06 января 2010

3-уровневая архитектура может иметь разные значения в зависимости от контекста. Обычно это означает, что обязанности в приложении разделены между различными уровнями. Как правило, 3-х уровневый относится к:

  • уровень представления "(фактический пользовательский интерфейс)
  • логический уровень (приложение / бизнес-логика)
  • уровень данных (база данных, хранилище данных)

Подробности зависят от приложения.

В Википедии, как обычно, есть хороший обзор: http://en.wikipedia.org/wiki/Multitier_architecture

Простым примером будет типичное бизнес-приложение:

  • презентация: браузер или толстый клиент
  • логический уровень: бизнес-логика, обычно на сервере приложений (на основе J2EE, ASP.NET или чего-либо еще)
  • уровень данных: база данных, обычно СУБД, такая как MySQL или Oracle
4 голосов
/ 06 января 2010

Уровень представления : поставить все, что связано с пользовательским интерфейсом. (Что видит пользователь)

Бизнес-уровень : все, что связано с логикой приложения (как обрабатывается информация, поступающая с уровня представления)

Уровень данных : предоставить абстракцию базового источника (-ов) данных (где и как хранится информация, поступающая с бизнес-уровня или поступающая на него)

Каждый слой должен знать как можно меньше о другом, и это должен быть подход сверху вниз:

  • слой данных не должен знать ничего о бизнесе и представлении
  • бизнес-уровень должен знать о данных, но не о представлении
  • презентация должна знать о бизнесе, а не о данных

Простой пример:

Сайт:

  • Презентация: все графические элементы, поля, в которые пользователь вставляет данные, меню, изображения и т. Д.
  • Бизнес: все ограничения для данных (уникальное имя, имя без символов, действительная дата и т. Д.), Методы управления бизнес-объектами (создание нового пользователя, добавление нового заказа и т. Д.)
  • Данные: методы доступа к базовой базе данных.
2 голосов
/ 06 января 2010

3-уровневая архитектура обычно имеет следующие компоненты:

  1. Клиентский браузер
  2. Веб-сервер, на котором размещено приложение ASP.NET
  3. Некоторое внутреннее хранилище, такое как база данных, к которой обращается приложение ASP.NET

Итак, чтобы ответить на ваш вопрос о том, как писать код для 3-уровневой архитектуры, вы разрабатываете приложение ASP.NET, которое взаимодействует с хранилищем данных.

0 голосов
/ 20 апреля 2015
connection class
-----------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Web .UI.WebControls ;
/// <summary>
/// Summary description for conn
/// </summary>
namespace apm_conn
{
    public class conn
    {
        public SqlConnection getcon()
        {
            SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["connect"].ConnectionString );
            if (con.State == ConnectionState.Closed)
            {
                con.Open();
            }
            return con;
        }
        #region execute command
        public string  Executecommand(SqlParameter []sqlparm,string sp)
        {
            string r_val = "";
            try
            {

                SqlConnection con = new SqlConnection();
                con = getcon();
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = con;
                cmd.CommandText = sp;
                cmd.CommandType = CommandType.StoredProcedure;
                foreach (SqlParameter loopvar_parm in sqlparm)
                {
                    cmd.Parameters.Add(loopvar_parm);

                }
                cmd.Parameters.Add("@Var_Output", SqlDbType.VarChar, 20).Direction = ParameterDirection.Output;
                cmd.ExecuteNonQuery();
                r_val = (string)cmd.Parameters["@Var_Output"].Value;
                con.Close();
            }
            catch { }
            return r_val;

        }

        #endregion
        #region Execute Dataset
         public DataSet ExeccuteDataset(SqlParameter[] sqlParm, string sp)
    {
        DataSet ds = new DataSet();
        try
        {
            SqlConnection con = new SqlConnection();
            con = getConn();
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = sp;
            foreach (SqlParameter LoopVar_param in sqlParm)
            {
                cmd.Parameters.Add(LoopVar_param);
            }
            cmd.ExecuteNonQuery();
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            da.Fill(ds);

        }
        catch
        { }
        return ds;
    }
        #endregion
        #region grid
        public void Bindgrid(DataSet ds,GridView g)
        {
            try
            {
                g.DataSource = ds.Tables[0];
                g.DataBind();

            }
            catch { }
        }
        #endregion
        #region Dropdownlist
        public void Binddropdown(DropDownList dl,DataSet ds,string text,string value)
        {
            try
            {
                dl.DataSource = ds.Tables[0];
                dl.DataTextField = text;
                dl.DataValueField = value;
                dl.DataBind();
            }
            catch
            {}

        }
        #endregion
        public conn()
        {
            //
            // TODO: Add constructor logic here
            //
        }
    }
}




dal
---------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using apm_conn;
using System.Data.SqlClient;
using apm_ent;

/// <summary>
/// Summary description for Class1
/// </summary>
namespace apm_dal
{
    public class dal
    {
        conn ob_conn = new conn();
        public dal()
        {
            //
            // TODO: Add constructor logic here
            //
        }
        public string insert(ent obj_ent)
        {
            SqlParameter[] sqlparm =
        {
            new SqlParameter ("@Var_Action",obj_ent.Var_Action),
            new SqlParameter ("@Int_Id",obj_ent.Int_Id ),
             new SqlParameter ("@Var_Product",obj_ent.Var_Product ),
              new SqlParameter ("@Dc_Price",obj_ent.Var_Price ),
              new SqlParameter ("@Int_Stat",obj_ent.Int_Stat ),

                               };
            return ob_conn.Executecommand(sqlparm, "Proc_product");
        }
        public string ins(ent obj_ent)
        {
            SqlParameter[] parm =
        {
            new SqlParameter ("@Var_Action",obj_ent .Var_Action),
            new SqlParameter ("@Int_Id",obj_ent .Int_Id),
                            };
            return ob_conn.Executecommand(parm, "Proc_product");
        }
    }

}

bal
-------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using apm_ent;
using apm_dal;

/// <summary>
/// Summary description for bal
/// </summary>
namespace apm_Bal
{

    public class bal
    {
        dal ob_dal = new dal();
        string r_val = "";
        public bal()
        {
            //
            // TODO: Add constructor logic here
            //
        }
        public string insert(ent obj_ent)
        {
            return ob_dal.insert(obj_ent);
        }
    }
}



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

/// <summary>
/// Summary description for ent
/// </summary>
namespace apm_ent
{
    public class ent
    {
        public ent()
        {
            //
            // TODO: Add constructor logic here
            //
        }
        #region Ent
        public int Int_Id { get; set; }
        public string  Var_Action { get; set; }
        public string Var_Product { get; set; }
        public decimal  Var_Price { get; set; }
        public int Int_Stat { get; set; }
        #endregion
    }
}



page code
--------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using apm_conn;
using apm_ent;
using apm_Bal;
using apm_conn;
public partial class _Default : System.Web.UI.Page
{
    conn obj_conn = new conn();
    ent obj_ent = new ent();
    bal obj_bal = new bal();
    string r_val = "";
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void btnsub_Click(object sender, EventArgs e)
    {
        obj_ent.Var_Action = "INS";
        obj_ent.Var_Product = txtproduct.Text;
        obj_ent.Var_Price = Convert.ToDecimal (txtprice.Text);
        r_val = obj_bal.insert(obj_ent);
        if (r_val == "1")
        {
            Response.Write("<script>alert('Inserted Sucessfully')</script>");
        }
    }
}
0 голосов
/ 29 июня 2012

Трехуровневая (уровень) - это клиент-серверная архитектура, в которой пользовательский интерфейс, бизнес-процесс (бизнес-правила) и хранилище данных и доступ к данным разрабатываются и поддерживаются как независимые модули или чаще всего на отдельных платформах.

В основном, есть 3 слоя:

  • уровень 1 (уровень представления, уровень GUI)
  • уровень 2 (бизнес-объекты, уровень бизнес-логики)
  • уровень 3 (уровень доступа к данным). Эти уровни можно разрабатывать и тестировать отдельно.

Зачем нужно делить код на 3 уровня? Отделение пользовательского интерфейса от бизнес-логики и доступа к базе данных имеет много преимуществ. Вот некоторые из преимуществ:

Повторное использование компонента бизнес-логики приводит к быстрому развитие. Допустим, у нас есть модуль, который обрабатывает добавление, обновление, удаление и поиск клиентов в системе. Как этот компонент разработано и протестировано, мы можем использовать его в любом другом проекте, который может привлечь клиентов.

Преобразование системы легко. Поскольку бизнес-логика отдельно от уровня доступа к данным, изменение уровня доступа к данным не сильно повлияет на модуль бизнес-логики. Скажем, если мы переход от хранилища данных SQL Server к Oracle не должно быть никаких изменения, необходимые в компоненте бизнес-уровня и в графическом интерфейсе компонент.

Изменить систему управления легко. Скажем, если есть несовершеннолетний изменение бизнес-логики, нам не нужно устанавливать весь система в персональных компьютерах пользователей. Например. если GST (НАЛОГ) изменен с 10% до 15% нам нужно только обновить компонент бизнес-логики без влияет на пользователей и без простоев.

Наличие отдельных функциональных серверов позволяет параллельную разработку отдельных ярусов специалистами по применению.

Обеспечивает более гибкое распределение ресурсов. Может уменьшить сеть трафик, имея функциональные серверы обрезать данные до точного структура, необходимая перед отправкой клиентам.

0 голосов
/ 06 января 2010

Хорошее учебное пособие с полным исходным кодом для загрузки хорошо написанного многоуровневого приложения будет здесь:

http://nerddinnerbook.s3.amazonaws.com/Intro.htm

Это не учебник по многоуровневой архитектуре, но это хорошо написанное приложение, которое дает некоторое представление о том, почему вы можете рассмотреть эту архитектуру.

Кроме того, как было кратко затронуто выше, речь идет о разделении кода логики / хранилища / презентации отдельно, поэтому, если вам нужно изменить один из них (например, перейти с внешнего интерфейса asp.net на настольное приложение) , это не так сложно сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...