1. 程式人生 > >.net 網站(MVC)三層架構實踐程式碼

.net 網站(MVC)三層架構實踐程式碼

一.任務

    建立一個.Net,C#,MVC的網站,採用三層架構,實現對一個Sql server中表資料的查詢。

二.何謂三層架構

    三層架構,指的是把系統分成三個部分:資料處理層(DAL:data access layer),業務邏輯層(BLL:business logical layer),表現層(USL:user show layer)。資料處理層:負責直接對資料庫的增刪改查。業務邏輯層:呼叫資料處理層,針對具體業務,把結果轉給表現層。表現層:負責和使用者互動(輸入,輸出)。

三.何謂MVC

    MVC(Model,View,Controller),模型-檢視-控制器。模型:指的是資料模型,簡單講,比如模型中可以

包含一個類person,具有name,sex,tele等屬性,當然模型內容更加可以直接用ADO.NET實體資料模型。

檢視:與使用者互動展示資料。控制器:負責尋找即將響應的檢視,並從模型層拿到資料,填充給檢視層,再

把檢視層展現出來。不同於WebForm的網站,WebForm網站中使用者直接訪問的就是各個aspx網頁,而MVC

的網站使用者直接訪問的是控制器類中的方法,每個方法去準備資料,再呈現檢視。

    個人以為,可以把.Net  的WebForm方式和MVC方式看做兩種開發網站的不同方式。前者更易上手開發速度快,而後者

在系統非常龐大而複雜時更易維護但較之前者難度大。

四.步驟
1.解決方案結構和說明



各專案名簡寫~

IBLL:業務邏輯層的介面

IDAL:資料處理層的介面

BLL:業務邏輯層

Common:存放解決方案中可公用的類,如SqlHelper.cs之類

DAL:資料處理層

Model:存放資料模型

MvcApp:Web表現層

注意:各個專案之間要新增必要的相互的引用。

2.詳細結構

IBLL:類庫,業務邏輯層的介面,添加了兩個介面

IDAL:類庫,資料處理層的介面,添加了三個介面


BLL:類庫,業務邏輯層,添加了兩個類


Common:類庫,存放解決方案中可公用的類,如SqlHelper.cs之類,這裡沒有用到公用的類,什麼也沒新增


DAL:類庫,資料處理層,添加了三個類


Model:類庫,存放資料模型,添加了ADO.NET實體資料模型Model1.edmx,對應資料表MyUser


MvcApp:MVC3專案,Web表現層,添加了控制器HomeController.cs,添加了檢視Index.cshtml, Create.cshtml


3.各個新增類,介面等的說明

1)Model,在Model裡新增實體資料模型,加入Sql server中的表MyUsers。


2)IDAL,

a.新增介面 IBaseDal.cs

using CZBK.Shop.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CZBK.Shop.IDAL
{
    //放公共方法
    public interface IBaseDal<T>where T:class,new()//約束T的型別,是一個類,並且可以new()
    {
        IQueryable<T> LoadEntities(Func<T,bool>whereLambda);
        T AddEntity(T item);
        bool DeleteEntity(T item);
        bool UpdateEntity(T item);
    }
}
b.新增介面 IDBSecssion.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data.Objects;

namespace CZBK.Shop.IDAL
{
    public interface IDBSecssion
    {
        IUserInfoDal UserInfoDal { get; set; }

        int ExecuteSql(string sql, params ObjectParameter[] pars);
        //params  關鍵字可以指定採用數目可變的引數的方法引數
        int SaveChanges();
    }
}
c.新增介面 IUserInfoDal.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CZBK.Shop.Model;

namespace CZBK.Shop.IDAL
{
    //有專門屬於MyUsers的介面方法寫在下面
    public interface IUserInfoDal:IBaseDal<MyUsers>
    {
       
    }
}

3)DAL

a.新增類 BaseDal.cs

using CZBK.Shop.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace CZBK.Shop.DAL
{
    public class BaseDal<T> where T:class,new()
    {
        //ExcrciseEntities db = new ExcrciseEntities();
        ExcrciseEntities db = DbContextFactory.GetCurrentContext();

        public IQueryable<T> LoadEntities(Func<T, bool> whereLambda)
        {
            return db.Set<T>().Where<T>(whereLambda).AsQueryable();
        }

        public T AddEntity(T item)
        {
            db.Set<T>().Add(item);
            //db.SaveChanges();
            return item;
        }

        public bool DeleteEntity(T item)
        {
            db.Set<T>().Remove(item);
            //return db.SaveChanges() > 0;
            return true;
        }

        public bool UpdateEntity(T item)
        {
            db.Entry(item).State = EntityState.Modified;
            //return db.SaveChanges() > 0;
            return true;
        }
    }
}

b.新增類 DbContextFactory.cs
using CZBK.Shop.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;

namespace CZBK.Shop.DAL
{
    //CallContext保證執行緒內建立的資料操作上下文是唯一的。
    public class DbContextFactory
    {
        public static ExcrciseEntities GetCurrentContext()
        {
            ExcrciseEntities DbContext = (ExcrciseEntities)CallContext.GetData("context");
            if (DbContext == null)
            {
                DbContext = new ExcrciseEntities();
                CallContext.SetData("context",DbContext);
            }
            return DbContext;
        }
    }
}
c.新增類 DBSession.cs
using CZBK.Shop.IDAL;
using CZBK.Shop.Model;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Objects;
using System.Data;
using System.Linq;
using System.Text;

namespace CZBK.Shop.DAL
{
    /// <summary>
    /// 所有的資料操作類的物件,使得業務邏輯層利用該類可拿到所有資料層的資料物件
    /// </summary>

    public class DBSession : IDBSecssion
    {
        DbContext dbContext = new ExcrciseEntities();
        

        private IUserInfoDal _userInfoDal;
        public IUserInfoDal UserInfoDal
        {
            get
            {
                if (_userInfoDal == null)
                {
                    _userInfoDal = new UserInfoDao();
                }
                return _userInfoDal;
            }
            set
            {
                _userInfoDal = value;
            }
        }




        public int ExecuteSql(string sql,params ObjectParameter[] pars)
        {
            return dbContext.Database.ExecuteSqlCommand(sql, pars);
        }

        //將業務涉及到的操作一次性的提交回資料庫
        public int SaveChanges()
        {
            return dbContext.SaveChanges();
        }
    }
}

d.新增類 UserInfoDao.cs
using CZBK.Shop.IDAL;
using CZBK.Shop.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data;

namespace CZBK.Shop.DAL
{
    public class UserInfoDao:BaseDal<MyUsers>,IUserInfoDal
    {
        
    }
}
4)IBLL

a.新增介面 IBaseManager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CZBK.Shop.IDAL;

namespace CZBK.Shop.IBLL
{
    public interface IBaseManager<T> where T:class,new()
    {
        IDBSecssion dbSecssion { get; }
        IBaseDal<T> CurrentDal { get; set; }
        IQueryable<T> LoadEntities(Func<T,bool> whereLambda);

        bool AddEntity(T entity);
        bool UpdateEntity(T entity);
        bool DeleteEntity(T entity);
    }
}
b.新增介面 IUserInfoManager.cs
using CZBK.Shop.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CZBK.Shop.IBLL
{
    public interface IUserInfoManager:IBaseManager<MyUsers>
    {
       
    }
}
5)BLL

a.新增類 BaseManager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CZBK.Shop.DAL;
using CZBK.Shop.IDAL;
namespace CZBK.Shop.BLL
{
    //業務層中公共的內容
    public abstract class BaseManager<T> where T:class,new()
    {
        public IDBSecssion dbSecssion
        {
            get{ return new DBSession(); }
        }

        //當前要用到的資料操作類的例項
        public IBaseDal<T> CurrentDal
        {
            get;
            set;
        }

        public abstract void SetCurrentDal();

        public BaseManager()//子類必須實現該抽象方法
        {
            SetCurrentDal();
        }

        public IQueryable<T> LoadEntities(Func<T,bool>whereLambda)
        {
            return CurrentDal.LoadEntities(whereLambda);
        }

        public bool AddEntity(T entity)
        {
            CurrentDal.AddEntity(entity);
            return dbSecssion.SaveChanges() > 0;
        }

        public bool DeleteEntity(T entity)
        {
            CurrentDal.DeleteEntity(entity);
            return dbSecssion.SaveChanges() > 0;

        }

        public bool UpdateEntity(T entity)
         {
            CurrentDal.UpdateEntity(entity);
            return dbSecssion.SaveChanges() > 0;
        }

    }        
}
b.新增類 UserInfoManager.cs
using CZBK.Shop.IBLL;
using CZBK.Shop.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//BLL業務邏輯層
namespace CZBK.Shop.BLL
{
    public class UserInfoManager : BaseManager<MyUsers> ,IUserInfoManager
    {

        public override void SetCurrentDal()
        {
            CurrentDal = this.dbSecssion.UserInfoDal;
        }

        //public void SetInfo()
        //{
        //    dbSecssion.UserInfoDal.AddEntity(userInfo);
        //}

    }
}
6)Common,這個專案裡暫時沒有新增任何東西。

7)MvcApp

a.在Controllers資料夾下新增控制器HomeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using CZBK.Shop.IBLL;
using CZBK.Shop.IDAL;
using CZBK.Shop.BLL;
using CZBK.Shop.DAL;
using CZBK.Shop.Model;

namespace CZBK.Shop.MvcApp.Controllers
{
    public class HomeController : Controller
    {

        IBLL.IUserInfoManager bll = new UserInfoManager();

        public ActionResult Index()
        {
            var temp = bll.LoadEntities(u => true);
            return View(temp);
        }

        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(MyUsers user)
        {
            bll.AddEntity(user);
            return RedirectToAction("Index");
        }
    }
}
b.在上面控制器HomeController.cs的 Index方法上右擊-新增檢視-強型別-List-Razor,

專案自動在Views資料夾下生成Index.cshtml,該檔案無需更改。

c.在Create方法上右擊右擊-新增檢視-強型別-Create-Razor,
專案自動在Views資料夾下生成Create.cshtml,該檔案無需更改。


4.不斷地生成每個寫好的專案,最後執行,預設結果頁面

點選左上角Create New,進入create頁面:


5. BUG!!!  嘗試結果,Index方法和頁面執行正常。
    但是在Create頁面新增一條記錄還無法儲存到資料庫。。。待改進。。。