MVC項目實踐,在三層架構下實現SportsStore-02,DbSession層、BLL層


SportsStore是《精通ASP.NET MVC3框架(第三版)》中演示的MVC項目,在該項目中涵蓋了MVC的眾多方面,包括:使用DI容器、URL優化、導航、分頁、購物車、訂單、產品管理、圖像上傳......是不錯的MVC實踐項目,但該項目不是放在多層框架下開發的,離真實項目還有一段距離。本系列將嘗試在多層框架下實現SportsStore項目,並用自己的方式實現一些功能。

 

本篇為系列第二篇,包括:

■ 4、三層架構設計
    □ 4.2 創建DbSession層 數據訪問層的統一入口 
        ※ 4.2.1 MySportsStore.IDAL詳解
        ※ 4.2.2 MySportsStore.DAL詳解
    □ 4.3 創建BLL層       
        ※ 4.3.1 MySportsStore.IBLL詳解
        ※ 4.3.2 MySportsStore.BLL詳解
       

  4.2 創建DbSession層 數據訪問層的統一入口

DbSession層主要做了3件事:
1、提交所有變化
2、拿到各個IXXXRepository類型
3、執行SQL語句

 

  4.2.1 MySportsStore.IDAL詳解

→IDbSession接口,數據庫訪問層的統一入口

using System.Data.SqlClient;

namespace MySportsStore.IDAL
{
    public interface IDbSession
    {
        //獲取所有的倉儲接口
        IProductRepository ProductRepository { get; set; }
        
        //保存所有變化
        int SaveChanges();

        //執行sql語句
        int ExeucteSql(string sql, params SqlParameter[] paras);
    }
}

→IDbSessionFactory接口,IDbSession接口的抽象工廠

在BaseRepository中會用到IDbSession的實例,我們借助"抽象工廠"生產IDbSession的實例。

namespace MySportsStore.IDAL
{
    public interface IDbSessionFactory
    {
        IDbSession GetCurrentDbSession();
    }
}

 

  4.2.2 MySportsStore.DAL詳解

→DbSession,對IDbSession接口的實現

using System.Data.Entity;
using MySportsStore.IDAL;

namespace MySportsStore.DAL
{
    public class DbSession : IDbSession
    {
        private IProductRepository _ProductRepository;
        public IProductRepository ProductRepository
        {
            get
            {
                if (_ProductRepository == null)
                {
                    _ProductRepository = new ProductRepository();
                }
                return _ProductRepository;
            }
            set { _ProductRepository = value; }
        }

        public int SaveChanges()
        {
            IDbContextFactory dbFactory = new DbContextFactory();
            DbContext db = dbFactory.GetCurrentThreadInstance();
            return db.SaveChanges();
        }

        public int ExeucteSql(string sql, params System.Data.SqlClient.SqlParameter[] paras)
        {
            IDbContextFactory dbFactory = new DbContextFactory();
            DbContext db = dbFactory.GetCurrentThreadInstance();
            return db.Database.ExecuteSqlCommand(sql, paras);
        }
    }
}

→DbSessionFactory,實現IDbSessionFactory接口,生產線程內唯一數據層訪問入口實例

using System.Runtime.Remoting.Messaging;
using MySportsStore.IDAL;

namespace MySportsStore.DAL
{
    public class DbSessionFactory: IDbSessionFactory
    {
        public IDbSession GetCurrentDbSession()
        {
            IDbSession dbSession = CallContext.GetData(typeof (DbSession).FullName) as IDbSession;
            if (dbSession == null)
            {
                dbSession = new DbSession();
                CallContext.SetData(typeof(DbSession).FullName, dbSession);
            }
            return dbSession;
        }
    }
}

 

  4.3 創建BLL層

  4.3.1 MySportsStore.IBLL詳解

→添加引用

● 添加對MySportsStore.Model的引用
● 添加對MySportsStore.IDAL的引用

→IBaseService,是所有IXXXService接口的泛型基接口實現,避免了所有IXXXService接口的重復部分

using System;
using System.Linq;
using System.Linq.Expressions;
using MySportsStore.IDAL;

namespace MySportsStore.IBLL
{
    public interface IBaseService<T> where T : class, new()
    {
         //數據層訪問統一入口工廠
        IDbSessionFactory DbSessionFactory { get; set; }

        //數據層訪問統一入口
        IDbSession DbSessionContext { get; set; }

        //查詢
        IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda);

        //分頁查詢
        IQueryable<T> LoadPageEntities<S>(
            Expression<Func<T, bool>> whereLambada,
            Expression<Func<T, S>> orderBy,
            int pageSize,
            int pageIndex,
            out int totalCount,
            bool isASC);

        //查詢總數量
        int Count(Expression<Func<T, bool>> predicate);

        //添加
        T AddEntity(T entity);

        //批量添加
        int AddEntities(params T[] entities);

        //刪除
        int DeleteEntity(T entity);

        //批量刪除
        int DeleteBy(Expression<Func<T, bool>> whereLambda);

        //更新
        T UpdateEntity(T entity);

        //批量更新
        int UpdateEntities(params T[] entities);
    }
}

為什么需要DbSessionContext屬性?
--通過該屬性可以拿到類型為IXXXRepository的XXXRepository。

 

為什么需要DbSessionFactory屬性?
--通過該"抽象工廠"屬性可以生產DbSessionContext實例。

 

→IProductService,對基接口IBaseService<Product>的實現

using MySportsStore.Model;

namespace MySportsStore.IBLL
{
    public interface IProductService : IBaseService<Product>
    {
         
    }
}

 

  4.3.2 MySportsStore.BLL詳解

→添加引用

● 添加對MySportsStore.Model的引用
● 添加對MySportsStore.IDAL的引用
● 添加對MySportsStore.IBLL的引用

 

→BaseService

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using MySportsStore.DAL;
using MySportsStore.IDAL;

namespace MySportsStore.BLL
{
    public abstract class BaseService<T> : IDisposable where T:class,new()
    {
        //數據層統一訪問入口工廠屬性
        private IDbSessionFactory _DbSessionFactory;

        public IDbSessionFactory DbSessionFactory
        {
            get
            {
                if (_DbSessionFactory == null)
                {
                    _DbSessionFactory = new DbSessionFactory();
                }
                return _DbSessionFactory;
            }
            set { _DbSessionFactory = value; }
        }

        //數據層統一訪問入口屬性
        private IDbSession _DbSessionContext;

        public IDbSession DbSessionContext
        {
            get
            {
                if (_DbSessionContext == null)
                {
                    _DbSessionContext = DbSessionFactory.GetCurrentDbSession();
                }
                return _DbSessionContext;
            }
            set { _DbSessionContext = value; }
        }

        //當前Repository,在子類中實現--通過一個抽象方法在構造函數中設置
        protected IBaseRepository<T> CurrentRepository;

        //借助此方法在子類中的重寫,為XXXService設置當前Repository
        public abstract bool SetCurrentRepository();

        public BaseService()
        {
            this.DisposableObjects = new List<IDisposable>();
            this.SetCurrentRepository();
        }

        //查詢
        public IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda)
        {
            return this.CurrentRepository.LoadEntities(whereLambda);
        }

        public IQueryable<T> LoadPageEntities<S>(
            Expression<Func<T, bool>> whereLambada,
            Expression<Func<T, S>> orderBy,
            int pageSize,
            int pageIndex,
            out int totalCount,
            bool isASC)
        {
            return this.CurrentRepository.LoadPageEntities<S>(
                whereLambada,
                orderBy,
                pageSize,
                pageIndex,
                out totalCount,
                isASC);
        }

        //查詢總數量
        public int Count(Expression<Func<T, bool>> predicate)
        {
            return this.CurrentRepository.Count(predicate);
        }

        //添加
        public T AddEntity(T entity)
        {
            this.CurrentRepository.AddEntity(entity);
            DbSessionContext.SaveChanges();
            return entity;
        }

        //批量添加
        public int AddEntities(params T[] entities)
        {
            return this.CurrentRepository.AddEntities(entities);
        }

        //刪除
        public int DeleteEntity(T entity)
        {
            this.CurrentRepository.DeleteEntity(entity);
            return DbSessionContext.SaveChanges();
        }

        //批量刪除
        public int DeleteBy(Expression<Func<T, bool>> whereLambda)
        {
            this.CurrentRepository.DeleteBy(whereLambda);
            return DbSessionContext.SaveChanges();
        }

        //更新
        public T UpdateEntity(T entity)
        {
            this.CurrentRepository.UpdateEntity(entity);
            if (this.DbSessionContext.SaveChanges() <= 0)
            {
                return null;
            }
            return entity;
        }

        //批量更新
        public int UpdateEntities(params T[] entities)
        {
            return this.CurrentRepository.UpdateEntities(entities);
        }

        public IList<IDisposable> DisposableObjects { get; private set; }

        protected void AddDisposableObject(object obj)
        {
            IDisposable disposable = obj as IDisposable;
            if (disposable != null)
            {
                this.DisposableObjects.Add(disposable);
            }
        }

        public void Dispose()
        {
            foreach (IDisposable obj in this.DisposableObjects)
            {
                if (obj != null)
                {
                    obj.Dispose();
                }
            }
        }
    }
}

BaseService是所有XXXService的泛型基類實現。

 

關鍵點一:如何在BaseService的子類中確定當前存儲CurrentRepository?
1、抽象基類BaseServic有類型為 IBaseRepository<T>的屬性CurrentRepository
2、通過在抽象基類BaseServic的構造函數中實現抽象方法SetCurrentRepository(),來設置CurrentRepository
3、BaseServic的子類必須重寫SetCurrentRepository()以最終確定當前的CurrentRepository值


關鍵點二:如何把BaseService的子類中的CurrentRepository銷毀?
1、在BaseService創建一個類型為IList<IDisposable>的集合
2、在BaseService中提供一個AddDisposableObject(object obj)方法,允許子類把CurrentRepository放入其中
3、在BaseService的Dispose()方法中,遍歷所有的CurrentRepository進行銷毀

 

→ProductService,派生於BaseService<Product>,實現IProductService接口

using MySportsStore.IBLL;
using MySportsStore.Model;

namespace MySportsStore.BLL
{
    public class ProductService : BaseService<Product>, IProductService
    {
        public ProductService():base(){}

        public override bool SetCurrentRepository()
        {
            this.CurrentRepository = DbSessionContext.ProductRepository;
            this.AddDisposableObject(this.CurrentRepository);
            return true;
        }
    }
}

至此,完成了三層架構的代碼實現。

源碼在這里

 

“MVC項目實踐,在三層架構下實現SportsStore”系列包括:

MVC項目實踐,在三層架構下實現SportsStore,從類圖看三層架構

MVC項目實踐,在三層架構下實現SportsStore-01,EF Code First建模、DAL層等

MVC項目實踐,在三層架構下實現SportsStore-02,DbSession層、BLL層

MVC項目實踐,在三層架構下實現SportsStore-03,Ninject控制器工廠等

MVC項目實踐,在三層架構下實現SportsStore-04,實現分頁

MVC項目實踐,在三層架構下實現SportsStore-05,實現導航

MVC項目實踐,在三層架構下實現SportsStore-06,實現購物車

MVC項目實踐,在三層架構下實現SportsStore-07,實現訂單提交

MVC項目實踐,在三層架構下實現SportsStore-08,部署到IIS服務器

MVC項目實踐,在三層架構下實現SportsStore-09,ASP.NET MVC調用ASP.NET Web API的查詢服務

MVC項目實踐,在三層架構下實現SportsStore-10,連接字符串的加密和解密

MVC項目實踐,在三層架構下實現SportsStore-11,使用Knockout實現增刪改查


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM