將商務邏輯層新增至使用模型系結和 Web 表單的專案

作者:Tom FitzMacken

本教學課程系列示範搭配 ASP.NET Web Forms專案使用模型系結的基本層面。 模型系結讓資料互動比處理資料來源物件更直接, (例如 ObjectDataSource 或 SqlDataSource) 。 本系列從簡介內容開始,並移至稍後教學課程中的更進階概念。

本教學課程說明如何搭配商務邏輯層使用模型系結。 您將設定 OnCallingDataMethods 成員,以指定使用目前頁面以外的物件來呼叫資料方法。

本教學課程是以系列 先前 部分建立的專案為基礎。

您可以在 C# 或 VB 中 下載 完整的專案。 可下載的程式碼適用于 Visual Studio 2012 或 Visual Studio 2013。 它會使用 Visual Studio 2012 範本,這與本教學課程中顯示的Visual Studio 2013範本稍有不同。

您將建置什麼

模型系結可讓您將資料互動程式碼放在網頁的程式碼後置檔案中,或放在個別的商務邏輯類別中。 先前的教學課程已示範如何使用程式碼後置檔案進行資料互動程式碼。 這種方法適用于小型網站,但在維護大型網站時,可能會導致程式碼重複和更困難。 因為沒有抽象層,所以以程式設計方式測試位於檔案後置程式碼的程式碼可能非常困難。

若要集中處理資料互動程式碼,您可以建立商務邏輯層,其中包含與資料互動的所有邏輯。 然後,您會從網頁呼叫商務邏輯層。 本教學課程示範如何將您在先前教學課程中撰寫的所有程式碼移至商務邏輯層,然後從頁面使用該程式碼。

在本教學課程中,您將會:

  1. 將程式碼從程式碼後置檔案移至商務邏輯層
  2. 變更您的資料繫結控制項以呼叫商務邏輯層中的方法

建立商務邏輯層

現在,您將建立從網頁呼叫的 類別。 此類別中的方法看起來類似于您在上一個教學課程中使用的方法,並包含值提供者屬性。

首先,新增名為 BLL的新資料夾。

新增資料夾

在 BLL 資料夾中,建立名為 SchoolBL.cs的新類別。 它將會包含原本位於程式碼後置檔案中的所有資料作業。 方法幾乎與程式碼後置檔案中的方法相同,但會包含一些變更。

要注意的最重要變更是,您不再從 Page 類別的實例內執行程式碼。 Page 類別包含 TryUpdateModel 方法和 ModelState 屬性。 當此程式碼移至商務邏輯層時,您就不再擁有 Page 類別的實例來呼叫這些成員。 若要解決此問題,您必須將 ModelMethodCoNtext 參數新增至任何存取 TryUpdateModel 或 ModelState 的方法。 您可以使用此 ModelMethodCoNtext 參數來呼叫 TryUpdateModel 或擷取 ModelState。 您不需要變更網頁中的任何專案,即可考慮這個新參數。

以下列程式碼取代 SchoolBL.cs 中的程式碼。

using System;
using System.Linq;
using ContosoUniversityModelBinding.Models;
using System.Web.ModelBinding;
using System.Web.UI.WebControls;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;

namespace ContosoUniversityModelBinding.BLL
{
    public class SchoolBL : IDisposable
    {
        SchoolContext db = new SchoolContext();

        public IQueryable<Student> GetStudents([Control] AcademicYear? displayYear)
        {
            var query = db.Students.Include(s => s.Enrollments.Select(e => e.Course));

            if (displayYear != null)
            {
                query = query.Where(s => s.Year == displayYear);
            }

            return query;
        }

        public void InsertStudent(ModelMethodContext context)
        {
            var item = new Student();

            context.TryUpdateModel(item);
            if (context.ModelState.IsValid)
            {
                db.Students.Add(item);
                db.SaveChanges();
            }
        }

        public void DeleteStudent(int studentID, ModelMethodContext context)
        {
            var item = new Student { StudentID = studentID };
            db.Entry(item).State = EntityState.Deleted;
            try
            {
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException)
            {
                context.ModelState.AddModelError("",
                    String.Format("Item with id {0} no longer exists in the database.", studentID));
            }
        }

        public void UpdateStudent(int studentID, ModelMethodContext context)
        {
            Student item = null;
            item = db.Students.Find(studentID);
            if (item == null)
            {
                context.ModelState.AddModelError("", String.Format("Item with id {0} was not found", studentID));
                return;
            }

            context.TryUpdateModel(item);
            if (context.ModelState.IsValid)
            {
                db.SaveChanges();
            }
        }

        public IQueryable<Enrollment> GetCourses([QueryString] int? studentID)
        {
            var query = db.Enrollments.Include(e => e.Course)
                .Where(e => e.StudentID == studentID);
            return query;
        }

        private bool disposedValue = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposedValue)
            {
                if (disposing)
                {
                    db.Dispose();
                }
            }
            this.disposedValue = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}

修改現有的頁面以從商務邏輯層擷取資料

最後,您將使用程式碼後置檔案中的查詢,將 Pages Students.aspx、AddStudent.aspx 和 Courses.aspx 轉換成使用商務邏輯層。

在 Students、AddStudent 和 Courses 的程式碼後置檔案中,刪除或批註化下列查詢方法:

  • studentsGrid_GetData
  • studentsGrid_UpdateItem
  • studentsGrid_DeleteItem
  • addStudentForm_InsertItem
  • coursesGrid_GetData

您現在應該在與資料作業相關的程式碼後置檔案中沒有程式碼。

OnCallingDataMethods事件處理常式可讓您指定要用於資料方法的物件。 在 Students.aspx 中,新增該事件處理常式的值,並將資料方法的名稱變更為商務邏輯類別中方法的名稱。

<asp:GridView runat="server" ID="studentsGrid"
    ItemType="ContosoUniversityModelBinding.Models.Student" DataKeyNames="StudentID"
    SelectMethod="GetStudents"
    UpdateMethod="UpdateStudent" DeleteMethod="DeleteStudent"
    AllowSorting="true" AllowPaging="true" PageSize="4"
    AutoGenerateEditButton="true" AutoGenerateDeleteButton="true"
    AutoGenerateColumns="false" 
    OnCallingDataMethods="studentsGrid_CallingDataMethods">

在 Students.aspx 的程式碼後置檔案中,定義 CallingDataMethods 事件的事件處理常式。 在此事件處理常式中,您可以指定資料作業的商務邏輯類別。

protected void studentsGrid_CallingDataMethods(object sender, CallingDataMethodsEventArgs e)
{
    e.DataMethodsObject = new ContosoUniversityModelBinding.BLL.SchoolBL();
}

在 AddStudent.aspx 中,進行類似的變更。

<asp:FormView runat="server" ID="addStudentForm"
    ItemType="ContosoUniversityModelBinding.Models.Student"
    InsertMethod="InsertStudent" DefaultMode="Insert"
    OnCallingDataMethods="addStudentForm_CallingDataMethods"
    RenderOuterTable="false" OnItemInserted="addStudentForm_ItemInserted">
protected void addStudentForm_CallingDataMethods(object sender, CallingDataMethodsEventArgs e)
{
    e.DataMethodsObject = new ContosoUniversityModelBinding.BLL.SchoolBL();
}

在 Courses.aspx 中,進行類似的變更。

<asp:GridView runat="server" ID="coursesGrid"
    ItemType="ContosoUniversityModelBinding.Models.Enrollment"
    SelectMethod="GetCourses" AutoGenerateColumns="false"
    OnCallingDataMethods="coursesGrid_CallingDataMethods">
protected void coursesGrid_CallingDataMethods(object sender, CallingDataMethodsEventArgs e)
{
    e.DataMethodsObject = new ContosoUniversityModelBinding.BLL.SchoolBL();
}

執行應用程式,並注意所有頁面都如先前一樣運作。 驗證邏輯也正常運作。

結論

在本教學課程中,您會重新建構應用程式,以使用資料存取層和商務邏輯層。 您指定資料控制項使用的物件不是資料作業的目前頁面。