啊,终于到写三层架构的时候了,老实说,我都不知道自己这个算不算三层架构,姑且就当它是吧,具体属于哪一个体系,希望有大佬指点一下(^o^)/

不晓得有人注意到没有,我写了三篇博客,然后就改了三次标题ヽ( ̄▽ ̄)ノ,

从最开始的Core建数据库,到Core数据库操作,再到现在的Core建站,也算是下决心写个系列啊,,感觉要更好久的样子,,

好吧,不要在意那些细节,文中可能会有一些我不知道的坑,毕竟自己也是一边自学一边写,不过保证功能还是能用的,发现有坑记得说,,我改,,(〃'▽'〃)

// ===================emmm,我是分割线===================

强烈推荐阅读:设计模式六大原则 讲的相当浅显易懂,,

首先上一个截图,看看现在的项目结构,今天的主角是DataBase文件里面的那一堆项目啊,BLL,DAL和Interface,,Models是生成数据库时使用的,所以今天用不上,,

按我的理解,先说说正常的三层架构吧,

UI:界面层,这个层最简单,只是给BLL传递数据,然后,将BLL返回的数据进行一些处理,方便展示,

BLL:业务逻辑层,接收UI层给的数据,写一些业务逻辑,第一步干啥,第二步干啥,什么什么的,然后把界面需要的数据返回出去,感觉更像是一个API

DAL:数据访问层,BLL的业务逻辑处理时,总要涉及到数据库的操作,这时候就要用到DAL层了,,

还有一个Model层,用来传递数据的,,不在三层范畴,,,

不知道大家是怎么使用三层的,给大家展示一下以前学校教我们怎么用的三层架构啊,,

分别对应三个类,UI层:HomeController,BLL层:DT_UserBLL,DAL层:DT_UserDAL

         // UI层
public IActionResult Index(int userID)
{ // 根据条件,返回用户
// 和BLL说,给你一堆条件,帮我把这些人找出来
var userList = DT_UserBLL.GetUser(,); return View(userList); }
         /// <summary>
/// BLL层,返回符合条件的用户
/// </summary>
/// <param name="sex">性别</param>
/// <param name="age">年龄</param>
/// <returns></returns>
public List<DT_User> GetUser(int sex, int age)
{ #region 数据校验 // 性别检测,0:女,1:男
if (sex != && sex != )
// 拒绝人妖
return null; // 年龄检测,[0,150]岁
if (age < || < age)
// 拒绝妖怪
return null; #endregion // 和DAL说,数据我校验好了,不是恶搞,
// 帮我查出来这些人,然后我交给UI就完事儿了,,
return DT_UserDAL.GetUser(int sex, int age).ToList();
}
         /// <summary>
/// DAL层,返回符合条件的用户
/// </summary>
/// <param name="sex">性别</param>
/// <param name="age">年龄</param>
/// <returns></returns>
public IQueryable<DT_User> GetUser(int sex, int age)
{
DbContext DB = new DbContext(); return DB.Set<DT_User>().Where(c=>c.Sex==sex&&c.Age==age);
}

当时学着感觉蛮好的,挺新奇的一个编程思想,不过每一个数据表对应的DAL里面都得写一套增删查改,,简直是灾难,,[○・`Д´・ ○]

出来实习之后,花了个把星期,把我们老大写的一个框架看明白了,就按图索骥地写了起来,嘿嘿

其实和三层架构差不多的,只是把每个数据表对应的DAL里面的增删查改全部提出来,封装成了一个类,,

然后对这个类进行继承,具体操作如下,,,

首先啊,要大概了解一下依赖注入,,讲真,这个我也是一脸懵逼,所以就不复制百度百科了,,

说说自己的理解吧,,,,emmm,此处可能有大量谬论,建议不要被我误导了,看看就好,别往心里去

依赖注入这东西就好像一个全局的字典类型变量,,都是以键值对的方式存储的

因为注册依赖注入服务的大部分语法是酱紫的,,,

 services.AddTransient(typeof(IDT_UserService), typeof(DT_UserService));

而services这个变量的话,就像一个容器,用来存储这些键值对的,具体从哪来的,我也不知道,ヽ( ̄д ̄;)ノ

而要使用的话,语法是酱紫的,,,

     public class HomeController : Controller
{
private IDT_UserService _UserService; public HomeController(IDT_UserService _UserService)
{
// 依赖注入得到实例
this._UserService = _UserService;
} public IActionResult Index()
{
ViewBag.list = _UserService.LoadEntites(c => true); return View();
}
}

对的,完全不需要new,,其原理,,起码我不晓得,感觉甚是神奇,,

先注册一个依赖注入的服务,然后要实例的时候,直接在构造函数里面把键的类型写上就好,,

好了,灌毒就到此为止了,,还是继续上代码吧,,

首先,得写一个数据库操作的底层类DalService又因为很多地方调用,所以,肯定是泛型,,

然后为了解耦和方便注入,所以实现一个接口IDalService

我暂时只写了添加和查询的方法,,其他的方法可以自由发挥,,不过记得先写接口,然后去实现接口中新加的方法,,不然无法使用的,,

     public interface IDalService<T> where T : class, new()
{
T AddEntity(T entity); IQueryable<T> LoadEntites(Expression<Func<T, bool>> where); int SaveChanges(); }

IDalService

     /// <summary>
/// 数据访问层:DAL
/// </summary>
/// <typeparam name="T"></typeparam>
public class DalService<T> : IDalService<T> where T : class, new()
{ private DbContext DbWrite; /// <summary>
/// 获得数据库上下文
/// </summary>
/// <param name="dbContext">数据库上下文类,各自更改成自己的</param>
public DalService(DBCodeFirst dbContext)
{
DbWrite = dbContext;
} public T AddEntity(T entity)
{
DbWrite.Set<T>().Add(entity);
return entity;
} public IQueryable<T> LoadEntites(Expression<Func<T, bool>> where)
{
return DbWrite.Set<T>().Where(where);
} public int SaveChanges()
{
return DbWrite.SaveChanges();
} }

DalService

然后就没有DAL层啥事了,,咱们去看BLL层

同样的写一个业务逻辑的父级类BllService,依旧是泛型,以及实现接口IBllService

     public interface IBllService<T>where T : class, new()
{
T AddEntity(T entity,bool IsSave); IQueryable<T> LoadEntites(Expression<Func<T, bool>> where); int SaveChanges();
}

IBllService

     /// <summary>
/// 数据逻辑层:BLL
/// </summary>
public class BllService<T> : IBllService<T> where T : class, new()
{ /// <summary>
/// 数据库服务
/// </summary>
protected IDalService<T> DBService; public BllService(IDalService<T> dalService)
{
this.DBService = dalService;
} /// <summary>
/// 保存实体
/// </summary>
/// <param name="entity"></param>
/// <param name="IsSave"></param>
/// <returns></returns>
public T AddEntity(T entity, bool IsSave)
{
entity = DBService.AddEntity(entity);
if (IsSave)
{
if (SaveChanges() > )
return null;
}
return entity;
} /// <summary>
/// 查询数据
/// </summary>
/// <param name="where"></param>
/// <returns></returns>
public IQueryable<T> LoadEntites(Expression<Func<T, bool>> where)
{
return DBService.LoadEntites(where);
} /// <summary>
/// 保存数据库
/// </summary>
/// <returns></returns>
public int SaveChanges()
{
return DBService.SaveChanges();
}
}

BllService

然后基本就完成了,,我们可以在BLL层创建一个DT_User的逻辑处理类,继承BllService,并实现接口IDT_UserService

     public interface IDT_UserService : IBllService<DT_User>
{
DT_User Insert(); List<DT_User> GetList();
}

IDT_UserService

     public class DT_UserService : BllService<DT_User>, IDT_UserService
{
/// <summary>
/// 用于实例化父级,DBService变量
/// </summary>
/// <param name="dal"></param>
public DT_UserService(IDalService<DT_User> dal) : base(dal)
{ } public DT_User Insert()
{
DT_User user = new DT_User
{
Password = new Random().Next(, ) + "",
UserName = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
};
return AddEntity(user, true);
} public List<DT_User> GetList()
{
return LoadEntites(c => true).ToList();
} }

DT_UserService

最后使用的话,要把他们统统注册到服务里面,新建一个类DIBllRegister,用来注册这些和数据库相关的服务

     /// <summary>
/// Bll层依赖注入
/// </summary>
public class DIBllRegister
{ public void DIRegister(IServiceCollection services)
{
// 用于实例化DalService对象,获取上下文对象
services.AddTransient(typeof(IDalService<>), typeof(DalService<>)); // 配置一个依赖注入映射关系
services.AddTransient(typeof(IDT_UserService), typeof(DT_UserService));
}
}

DIBllRegister

在Startup的ConfigureServices方法中添加两行代码

         /// <summary>
/// 运行时调用此方法。使用此方法向容器添加服务。
/// </summary>
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions(); // 数据库连接字符串
var conStr = Config.GetVal<string>(ConfigKey.ConStr);
services.AddDbContext<DBCodeFirst>(options => options.UseSqlServer(conStr)); DIBllRegister bllRegister = new DIBllRegister();
bllRegister.DIRegister(services);

services.AddMvc();
}

然后我们就可以愉快的使用三层架构来写项目了,,ヽ(≧∀≦)ノ

示例以及项目结构如下:

运行结果:

注意事项:

  1. BLL层的类一定要继承BllService,并实现它对应的接口,参考上文DT_UserService类的格式
  2. BLL,DAL任何类要添加方法时,一定要在对应的接口中有个同样的入口,不然无法调用
  3. BLL层添加类时,记得在DIBllRegisterDIRegister中添加一行注册服务的代码,不然无法调用
  4. 差不多就这些,我想起来了再加,,,

其实这个是我从Framework搬过来的,心塞得简直不要不要的,,,填坑日记就不写出来了,,

具体的搭建思想也不太好用文字表述,大佬不要吐槽,萌新可以照着步骤去建一个小项目调试着看,,

个人感觉还是比较好懂的,,毕竟,基本上全是核心代码还带注释,加一个使用样例,

然后就是下集预告了,云服务器的FTP发布和数据库连接吧,,毕竟云服务器到手辣么久了,也该拉出来溜溜,,(❁´◡`❁)*✲゚*

最后,,有坑记得说,,,,

.Net Core建站(3):搭建三层架构的更多相关文章

  1. 关于ASP.NET或VS2005 搭建三层架构的理解

    最近想学习ASP.NET建网站,关于ASP.NET或VS2005 搭建三层架构的理解,网上摘录了一些资料,对于第(2)点的讲解让我理解印象深刻,如下: (1)为何使用N层架构? 因为每一层都可以在仅仅 ...

  2. HHvm Apache 2.4 Nginx建站环境搭建方法安装运行WordPress博客

    HHvm Apache 2.4 Nginx建站环境搭建方法安装运行WordPress博客 VPS主机   2014年06月02日 17:20   评论»       文章目录 Debian上安装 Ce ...

  3. CS通用项目系统搭建——三层架构第一天

    CS通用项目:使用三层架构进行搭建 三层架构: 表现层(UI(User Interface)):展示给用户的层面,包含窗体控件数据等信息. 业务逻辑层(BLL(Business Logic Layer ...

  4. HHvm建站环境搭建方法:Nginx,Mariadb,hhvm及lnmp/lamp安装部署

    HHVM起源于Facebook公司,是一个开源的PHP虚拟机,使用JIT的编译方式以及其他技术,让PHP代码的执行性能大幅提升.HHVM提升PHP性能的途径,采用的方式就是替代Zend引擎来生成和执行 ...

  5. 利用Dapper ORM搭建三层架构

    利用Dapper关系对象映射器写的简单的三层架构.Dapper:StackOverFlow在使用的一个微型的ORM,框架整体效率较高,轻量级的ORM框架.网上有较多的扩展.此处只是简单的调用Dappe ...

  6. 搭建三层架构(ASP.NET MVC+EF)

    昨天面试的时候最后做了一道上机题,竟然跪了,跪就跪在没有搭好框架,连接数据库总是程序报错. 回来之后亲自搭了一下框架,弄好后放到博客上.下图就是搭建好后,整个框架的结构就是这样,下面对框架中的文件进行 ...

  7. net core建站

    带你快速进入.net core的世界   阅读目录   vmware虚拟机安装 CentOS7.3安装 Windows的客户端软件 .NET Core1.1安装 nginx1.12.1安装 配置防火墙 ...

  8. .Net Core建站(1):EF Core+CodeFirst数据库生成

    emmm,本来想着用Core做一个小项目玩玩的,然后肯定是要用到数据库的, 然后想,啊,要不用CodeFirst,感觉很腻害的样子,于是,一脸天真无邪的我就踏入了一个深不见底的天坑... 本来想着,应 ...

  9. .net core建站踩坑记录

    系统:win10 VS版本:2017 .NET Core 版本: 1.1 零.读取配置文件 参考:http://www.tuicool.com/articles/QfYVBvi 此版本无需添加其他组件 ...

随机推荐

  1. ibv_get_device_guid()函数

    uint64_t ibv_get_device_guid(struct ibv_device *device); 描述 函数返回RDMA 设备的 GUID(The Global Unique IDen ...

  2. 室内地图1:从CAD到Map(画图,发布,路径导航)

    首先这个教程整理,比较偏细节. 因为我本身不是做GIS,所以可能有点流水账,当然错漏难免,恳请指正. 当我们做定位的时候,想要可视化展示,室外当然可以直接使用google,百度的底图.对于室内,有两种 ...

  3. 初识java这个小姑娘(二)

    妙解垃圾回收机制 周一,早高峰. 一段考验一个人耐力.智力.开车技术以及脾气的路. 我把车开进了一个没有红绿灯的丁字路口,然后就没有然后了. 来自三个方向的大车小车开始在不大的一块空间里开始互相斗智斗 ...

  4. django模板语法之include

    假如我们有以下模板index.html,代码为: <!DOCTYPE html> <html lang="en"> <head> <met ...

  5. IQKeyboardManager 状态栏(status bar)问题

    因为懒,所以具体什么样子,参考下面的链接 具体的问题情况参考:StatusBar background problem #1158 我解决的思路很简单,就是在监听键盘消失的时候,去设置 statys ...

  6. 安装phpnow服务[Apache_pn]提示失败的解决方法

    win 7/win 8/Win10 phpnow提示"安装服务[Apache_pn]失败"错误解决办法汇总 常常在安装phpnow的时候,提示"安装服务 [ Apache_pn ] 失败&q ...

  7. javaweb学习总结(七)——HttpServletResponse对象(一)(转)

    转载自 http://www.cnblogs.com/xdp-gacl/p/3789624.html Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对 ...

  8. java集合框架07——Map架构与源代码分析

    前几节我们对Collection以及Collection中的List部分进行了分析,Collection中还有个Set,因为Set是基于Map实现的,所以这里我们先分析Map,后面章节再继续学习Set ...

  9. ZOJ 2859 二维RMQ(模板)

    这题求范围最小值,RMQ正好是用来解决这方面的.所以再适合只是了,又是离线静态输入输出的,所以时间比二维线段树快. #include<iostream> #include<cstdi ...

  10. Android中相机和相冊使用分析

    Android中相机和相冊使用分析 欢迎转载,但请尊重原创(文章来自不易,转载请标明转载出处,谢谢) 在手机应用程序中,使用自带的相机拍照以及相冊选择喜欢的图片是最常见只是的用户需求,那么怎么合理使用 ...