掌上租項目架構總結


        掌上租項目是如鵬 .NET 課程中的一個實戰項目,架構搭建使用的是 Fluent API,實體都要手動去編寫,總覺得很麻煩,結合所學的知識,重新搭建項目架構,設計好數據庫,通過 ADO.NET 實體數據模型 + T4 ,自動生成各層基礎代碼。

 

項目源碼:https://gitee.com/linyq-gitee/ZSZDemo

 

項目架構示意圖:

 

項目架構總結:

一、使用 PowerDesigner 設計數據庫,生成sql腳本

 

二、執行 sql  創建數據庫

三、Model 層

通過 EF Database First 創建

 

數據很重要,數據刪除都是進行軟刪除

問題:BaseDal 中怎么進行軟刪除?

解決方案1:BaseDal 中對實體進行軟刪除

解決方案2:所有實體必須包含軟刪除字段,定義實體基類,所有實體都繼承這個基類

namespace ZSZ.Model { /// <summary>
    /// 約定大於配置 /// </summary>
   public abstract class BaseEntity { public long Id { get; set; } public bool IsDeleted { get; set; } public System.DateTime CreateDateTime { get; set; } } }

 BaseDal 軟刪除

public void Deleted(T entity) { ctx.Entry(entity).State = EntityState.Deleted; // ctx.SaveChanges();
}

 

四、DAL 層

問題:Dal 類中都有基礎的 CRUD 代碼

解決方案:Don't Repeat Yourself !  不要重復你自己

抽取基礎代碼定義基類 BaseDal

 

解耦第一步:接口

解耦第二步:工廠模式解決 new 的問題

 

問題:多個實體數據模型切換

解決方案:通過簡單工廠  DbContextFactory 創建實例

public partial class BaseDal<T> where T :BaseEntity { //DbContext ctx = new ZSZEntities();
    /// <summary>
    /// 多個實體數據模型切換 /// </summary>
    public DbContext ctx { get { return DbContextFactory.GetCurrentDbContext(); } } }

 

普通 Dal 類定義

public partial  class UserDal:BaseDal<User>, IUserDal { }

 

五、IDAL 層

問題:

1.跨數據庫 SQL Server 、MySQL

2.數據訪問驅動層切換  EFDAL、NHDAL

解決方案:依賴接口編程,通過接口方式解耦

基接口:IBaseDal

普通 Dal 接口定義:

public partial  class UserDal:BaseDal<User>, IUserDal { }

 

IDbSession 接口 (解耦 DALFactory 層 中的 DbSession )

 

六、DALFactory 層

問題:數據訪問層可能發生變化

IUserDal = new EFDAL.UserDal(); //IUserDal = new NHDAL.UserDal();

解決方案1:簡單工廠模式  

public partial class StaticDalFactory { public static IUserDal GetUserDal() { return EFDAL.UserDal(); } }

缺點:切換時需要大量替換

 

解決方案2:反射+抽象工廠

約定大於配置

  EFDAL.UserDal()

       NHDAL.UserDal()

 

Web.config

<appSettings>
  <!--抽象工廠創建數據庫訪問層實例所在的程序集名稱-->
  <add key="DalAssemblyName" value="ZSZDemo.EFDAL" />
</appSettings>

 

public partial class StaticDalFactory { public static string assemblyName = ConfigurationManager.AppSettings["DalAssemblyName"]; public static IUserDal GetUserDal() { return Assembly.Load(assemblyName).CreateInstance(assemblyName + ".UserDal") as IUserInfoDal; } }

 

解決方案3:IOC\DI  依賴注入

Spring.NET、AutoFac

 

 

new 一個 class 的時候,.NET 會現在內存堆中開辟一塊用來存放實例的空間,然后再對實例進行初始化,而開辟內存堆空間的時候,這些空間並不是連續的,所以當一個項目中大量地使用了 new 的時候,就會造成內存堆中存在大量地碎片,這種想象會對系統造成故障。

解決方案:構建 DbSession  , DbSession 把所有實體對應的 Dal 實例化,並保證 DbSession 在每個進程內都是唯一的

DbSession :整個數據庫和數據訪問層的會話

1.所有 Dal 的實例

2.SaveChanges ( )   方法

單元工作模式:權利交給客戶端,減少交互次數

應用:批量處理

 

通過 Spring.Net 注入

namespace ZSZ.DALFactory { public partial class DbSession : IDbSession { #region 通過 Spring.Net 注入
        public ISettingDal SettingDal { get; set; } #endregion

        public int SaveChanges() { return DbContextFactory.GetCurrentDbContext().SaveChanges(); } } }

 

通過 AutoFac 注入

public partial class DbSession : IDbSession { #region 通過 AutoFac 注入
    public IAdminLogDal AdminLogDal { get { return DependencyResolver.Current.GetService<IAdminLogDal>(); } } #endregion

    public int SaveChanges() { return DbContextFactory.GetCurrentDbContext().SaveChanges(); } }

 

 

 

 

DbSessionFactory

 

using DotNetMVC.IDAL; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Remoting.Messaging; using System.Text; using System.Threading.Tasks; namespace DotNetMVC.DALFactory { public class DbSessionFactory { public static IDbSession GetCurrentDbSession() { //return new DbSession();
            IDbSession dbSession = CallContext.GetData("DbSession") as IDbSession; if (dbSession == null) { dbSession = new DbSession(); CallContext.SetData("DbSession", dbSession); } return dbSession; } } }

 

 

 

七、Service 層

基類:BaseService

BaseService<T>  中的實例通過 Spring.Net 注入

public abstract class BaseService<T> where T : BaseEntity { public IBaseDal<T> CurrentDal { get; set; } public IDbSession DbSession { get { return DbSessionFactory.GetCurrentDbSession(); } } public BaseService() { //目的:CurrentDal 使用之前,初始化賦值
 SetCurrentDal(); } /// <summary>
    /// 抽象方法,要求子類必須實現 /// 目的:逼迫子類 CurrentDal 賦值 /// </summary>
    public abstract void SetCurrentDal(); /*********公共代碼*********/

 

 

public partial class AdminLogService:BaseService<AdminLog>, IAdminLogService { public override void SetCurrentDal() { CurrentDal = DbSession.AdminLogDal; } }

 

 

普通類:

public partial class UserService:BaseService<User>, IUserService { }

 

八、IService 層

層與層訪問使用接口隔離

 

九、T4 模板

各層基礎代碼通過 T4 模板生成

 十、DTO 層

DTO 一般是“扁平類”,也就是沒有關聯屬性,都是普通類型屬性。DTO有哪些屬性取決於其他層要什么數據。DTO類似於三層架構中的 Model。

 


免責聲明!

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



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