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实现增删改查

MVC项目实践,在三层架构下实现SportsStore-02,DbSession层、BLL层的更多相关文章

  1. MVC项目实践,在三层架构下实现SportsStore,从类图看三层架构

    在"MVC项目实践,在三层架构下实现SportsStore-02,DbSession层.BLL层"一文的评论中,博友浪花一朵朵建议用类图来理解本项目的三层架构.于是就有了本篇: I ...

  2. MVC项目实践,在三层架构下实现SportsStore-01,EF Code First建模、DAL层等

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  3. MVC项目实践,在三层架构下实现SportsStore-03,Ninject控制器工厂等

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  4. MVC项目实践,在三层架构下实现SportsStore-04,实现分页

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  5. MVC项目实践,在三层架构下实现SportsStore-05,实现导航

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  6. MVC项目实践,在三层架构下实现SportsStore-06,实现购物车

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  7. MVC项目实践,在三层架构下实现SportsStore-07,实现订单提交

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  8. MVC项目实践,在三层架构下实现SportsStore-08,部署到IIS服务器

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  9. MVC项目实践,在三层架构下实现SportsStore-09,ASP.NET MVC调用ASP.NET Web API的查询服务

    ASP.NET Web API和WCF都体现了REST软件架构风格.在REST中,把一切数据视为资源,所以也是一种面向资源的架构风格.所有的资源都可以通过URI来唯一标识,通过对资源的HTTP操作(G ...

随机推荐

  1. HTTP 笔记与总结(1 )Telnet 分别发送 HTTP GET 和 HTTP POST 请求

    简化的说: WebService = HTTP 协议 + XML Rest = HTTP 协议 + Json 各种 API = HTTP 协议 + XML / Json 来实现 HTTP 请求信息格式 ...

  2. 不再以讹传讹,GET和POST的真正区别

    不再以讹传讹,GET和POST的真正区别 网上的多数答案都是错的 在 2012年05月03日 那天写的     已经有 19940 次阅读了 感谢 参考或原文 www.cnblogs.com   服务 ...

  3. MySQL 数据库性能优化之SQL优化

    前言 有人反馈之前几篇文章过于理论缺少实际操作细节,这篇文章就多一些可操作性的内容吧. 注:这篇文章是以 MySQL 为背景,很多内容同时适用于其他关系型数据库,需要有一些索引知识为基础. 优化目标 ...

  4. 图片放大插件——elevatezoom

    GitHub地址:https://github.com/elevateweb/elevatezoom elevatezoom官网:http://www.elevateweb.co.uk/image-z ...

  5. Jquery scrollTop animate 實現動態滾動到頁面頂部

    這個方法之前都是用的錨點實現的,但是效果僵硬,動感不足! 之後參考了一些網站,發現都是用的js,於是自己想到用jquery 來做一個插件也來實現以下這個小功能. $.fn.backTop = func ...

  6. Bootstrap页面布局1 - 下载BS(bootstrap简称)

    1.bootstrap 官方网站:http://wrongwaycn.github.io/bootstrap/docs/index.html 2.如图: 3.下载后得到如下目录结构 bootstrap ...

  7. json一些特点

    1:mina框架中客户端信息到服务端信息的输出格式为json, 原因:json通过key-value对的集合,和xml相比,json数据的体积更加小,传输效率高,容易解析 缺点:可读性不高 2:

  8. Delphi 的绘图功能[1] - PolyBezier、PolyBezierTo

    双击代码全选 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 unit Unit1; interface uses Windows, Messages, SysUtils ...

  9. java实现的https请求

    转载并修改自 http://www.blogjava.net/etlan/archive/2006/06/29/55767.html Https请求 超文本传输协议HTTP协议:被用于在Web浏览器和 ...

  10. 我的第一个chrome扩展(3)——继续读样例

    1.操作用户正在浏览的界面 http://www.ituring.com.cn/article/60212 问题:1.google未定义ID,用name为何无法找到? 2.如何让整个按钮一起动?原函数 ...