您现在的位置是:网站首页> 编程资料编程资料

ASP.NET MVC5 网站开发框架模型、数据存储、业务逻辑(三)_实用技巧_

2023-05-24 343人已围观

简介 ASP.NET MVC5 网站开发框架模型、数据存储、业务逻辑(三)_实用技巧_

前面项目的层次和调用关系都说明了,关系如下图

采用三层架构的时候,研究过BLL层的必要性,觉得业务逻辑完全可以在controller里实现,没有必要单独做一个项目,另一个分层多了会影响性能。后来我还是把业务逻辑独立出来,原因如下:

  • 业务逻辑写进controller里代码看着比较混乱,时间久了代码容易理不清。
  • 在controller里直接写逻辑重复代码会不较多,开发效率低。
  • 分项目有利于代码重用,有时候可以直接拿到其他项目中稍作修改就可以用。

对于性能我觉得分层多了肯定会有影响,但是不会很大。现在硬件的更新速度远大于软件,对业务逻辑处理起来很轻松,多实例化几个类对性能影响不大。一般来说网站运行基本上是一个存数据库和取数据库的过程,业务逻辑还是比较少,只不过现在的网站使用的图片、动画更多,效果更加绚丽。我觉得网站的效率瓶颈主要出现在服务器的带宽、IO性能和存取数据库上。在代码方面能做的就是优化数据库的存取。对了一般项目来说,为了百分之几的运行效率远不如提高开发效率和更加容易的代码管理重要,能实现需求就好,运行效率是哪是大牛要做的事。

对IDAL、DAL、IBLL 、BLL这四个项目:

IDAL写一个Base接口,接口中固定几个数据库操作方法,其他接口都继承自这个接口;

DAL项目做个base类实现这个IDAL的base接口,其他类都继承自base类。

同样IBLL中也写一个Base接口,固定几个基本的操作方法,同样其他接口也继承自这个base接口

IBLL中也写一个base类来实现IBLL中的base接口,其他类继承自这个base类。

这里以对用户的操作来构建代码的基本模式:

一、模型

这里写三个模型类。打开Ninesk.Models分别添加User、UserGroup、UserConfig三个模型类。

1、用户模型—User类

用户模型或者叫账户模型,为什么这么说看下面代码

 using System; using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { ///  /// 用户模型 ///  /// 创建:2014.02.02
/// 修改:2014.02.05 ///
///
public class User { [Key] public int UserID { get; set; } /// /// 用户名 /// [Required(ErrorMessage="必填")] [StringLength(20,MinimumLength=4,ErrorMessage="{1}到{0}个字符")] [Display(Name="用户名")] public string UserName { get; set; } /// /// 用户组ID /// [Required(ErrorMessage = "必填")] [Display(Name = "用户组ID")] public int GroupID { get; set; } /// /// 显示名 /// [Required(ErrorMessage = "必填")] [StringLength(20, MinimumLength = 2, ErrorMessage = "{1}到{0}个字符")] [Display(Name = "显示名")] public string DisplayName { get; set; } /// /// 密码 /// [Required(ErrorMessage = "必填")] [Display(Name = "密码")] [DataType(DataType.Password)] public string Password { get; set; } /// /// 邮箱 /// [Required(ErrorMessage = "必填")] [Display(Name = "邮箱")] [DataType(DataType.EmailAddress)] public string Email { get; set; } /// /// 用户状态
/// 0正常,1锁定,2未通过邮件验证,3未通过管理员 ///
public int Status { get; set; } /// /// 注册时间 /// public DateTime RegistrationTime { get; set; } /// /// 上次登陆时间 /// public DateTime LoginTime { get; set; } /// /// 上次登陆IP /// public DateTime LoginIP { get; set; } public virtual UserGroup Group { get; set; } } }

这个模型类中只包含用户名、密码、用户组、显示名、邮箱等属性,纯粹是基本的账户信息,目的是让用户注册的时候尽可能的少填信息。其他信息如果需要可以再写新类与账户进行关联,用户需要的时候登录后再进行补填(如:资本资料、个人信息、联系方式等。这里先不考虑这些)。这里的显示名根据需要可以做昵称、真实姓名等来使用。

2、用户组模型—UserGroup类

这个类注意下GroupType,这个用来对用户组进行一下分类的,方便管理,其实没什么特别的意义。我的想法是普通类型就放普通的注册用户的组,如果大的网站允许用户升级的话,限定在这个类型的用户组内。特权组可以放一些vip之类的用户组,需要管理员给予,区别普通用户组,但又没有管理权。管理类型的用户组需要后台管理员给予,可以对文章、评论、咨询进行管理。

 using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { ///  /// 用户组 ///  /// 创建:2014.02.02 /// 修改:2014.02.08 ///  ///  public class UserGroup { [Key] public int GroupID { get; set; } ///  /// 名称 ///  [Required(ErrorMessage="必填")] [StringLength(20, MinimumLength = 2, ErrorMessage = "{1}到{0}个字")] [Display(Name="名称")] public string Name { get; set; } ///  /// 用户组类型
/// 0普通类型(普通注册用户),1特权类型(像VIP之类的类型),3管理类型(管理权限的类型) ///
[Required(ErrorMessage = "必填")] [Display(Name = "用户组类型")] public int GroupType { get; set; } /// /// 说明 /// [Required(ErrorMessage = "必填")] [StringLength(50, ErrorMessage = "少于{0}个字")] [Display(Name = "说明")] public string Description { get; set; } } }

3、用户配置模型类—UserConfig类

这个类是一些用户配置信息(暂时只考虑了注册设置),在后台管理员处进行设置。

 using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { ///  /// 用户配置 ///  /// 创建:2014.02.06 ///  ///  public class UserConfig { [Key] public int ConfigID { get; set; } ///  /// 启用注册 ///  [Display(Name = "启用注册")] [Required(ErrorMessage="必填")] public bool Enabled { get; set; } ///  /// 禁止使用的用户名
/// 用户名之间用“|”隔开 ///
[Display(Name = "禁止使用的用户名")] public string ProhibitUserName { get; set; } /// /// 启用管理员验证 /// [Display(Name = "启用管理员验证")] [Required(ErrorMessage = "必填")] public bool EnableAdminVerify { get; set; } /// /// 启用邮件验证 /// [Display(Name = "启用邮件验证")] [Required(ErrorMessage = "必填")] public bool EnableEmailVerify { get; set; } /// /// 默认用户组Id /// [Display(Name = "默认用户组Id")] [Required(ErrorMessage = "必填")] public int DefaultGroupId { get; set; } } }

二、数据存储层

数据存储层负责与数据库打交道,由于使用了接口产生了两个项目DAL和IDAL。IDAL是接口项目,DAL是接口的实现项目。

在与数据库的方便有一些共同的操作,像添加、修改、删除、查询等。不想在实际写代码的时候在用户类写一遍这些东西,用户组类再写一遍、以后文章、评论都再重复写这些代码。怎么办,弄个基类。以后其他类从基类继承就把这些公共方法继承过来了。

1、IDAL项目

首先打开IDAL项目,添加类InterfaceBaseRepository,代码如下。

 using System; using System.Linq; using System.Linq.Expressions; namespace Ninesky.IDAL { ///  /// 接口基类 /// 创建:2014.02.03 
/// 修改:2014.02.09
///
/// 类型 public interface InterfaceBaseRepository { /// /// 添加 /// /// 数据实体 /// 添加后的数据实体 T Add(T entity); /// /// 查询记录数 /// /// 条件表达式 /// 记录数 int Count(Expression> predicate); /// /// 更新 /// /// 数据实体 /// 是否成功 bool Update(T entity); /// /// 删除 /// /// 数据实体 /// 是否成功 bool Delete(T entity); /// /// 是否存在 /// /// 查询表达式 /// 布尔值 bool Exist(Expression> anyLambda); /// /// 查询数据 /// /// 查询表达式 /// 实体 T Find(Expression> whereLambda); /// /// 查找数据列表 /// /// 排序 /// 查询表达式 /// 是否升序 /// 排序表达式 /// IQueryable FindList(Expression> whereLamdba, bool isAsc, Expression> orderLamdba); /// /// 查找分页数据列表 /// /// 排序 /// 当前页 /// 每页记录数 /// 总记录数 /// 查询表达式 /// 是否升序 /// 排序表达式 /// IQueryable FindPageList(int pageIndex, int pageSize, out int totalRecord, Expression> whereLamdba, bool isAsc, Expression> orderLamdba); } }

这里定义了增、删、改、判断存在、返回模型的查询、返回集合的查询,返回分页集合的查询7个公共方法。这几个方法基本满足一般需要,特殊的方法在继承的时候再添加。
还使用了泛型,在继承的时候传入实体类型就可以直接继承这些方法了。具体看下InterfaceUserRepository接口就清楚了。

using Ninesky.Models; namespace Ninesky.IDAL { ///  /// 用户接口 /// 创建:2014.02.03 ///  public interface InterfaceUserRepository:InterfaceBaseRepository { } }

简单吧,继承自InterfaceBaseRepository接口并传入实体类User就行了。我们在类视图中看下,是不是继承了基类的接口。

2、DAL项目

DAL项目是对IDAL项目接口的实现,项目中要创建DbContext类,对于DbContext类很多人讨论过它对数据库存取的效率,MSDN中说其是轻量的, 创建不需要很大开销,它也不是线程安全的对象,并且具有数据容器的性质(跟踪),因此很多人认为不应该将其静态化、单例化。但是对用户的单次请求来说实现DbContext唯一是合理的。 先看代码吧,非常简单。

using Ninesky.Models; using System.Data.Entity; namespace Ninesky.DAL { ///  /// 数据上下文 /// 创建:2014.02.03 ///  public class NineskyDbContext:DbContext { public DbSet Users { get; set; } public DbSet UserGroups { get; set; } public DbSet UserConfig { get; set; } public NineskyDbContext() : base("DefaultConnection") { } } }

下面创建一个BaseRepository类,继承自InterfaceBaseRepository并实现类其接口的方法。

using Ninesky.IDAL; using System; using System.Linq; using System.Linq.Expressions; namespace Ninesky.DAL { ///  /// 仓储基类 /// 创建:2014.02.03 ///  public class BaseRepository: InterfaceBaseRepository where T : class { protected NineskyDbContext nContext = ContextFactory.GetCurrentContext(); public T Add(T entity) { nContext.Entry(entity).State = System.Data.Entity.EntityState.Added; nContext.SaveChanges(); return entity; } public int Count(Expression> predicate) { return nContext.Set().Count(predicate); } public bool Update(T entity) { nContext.Set().Attach(entity); nContext.Entry(entity).State = System.Data.Entity.EntityState.Modified; return nContext.SaveChanges() > 0; } public bool Delete(T entity) { nContext.Set().Attach(entity); nContext.Entry(entity).State = System.Data.Entity.EntityState.Deleted; return nContext.SaveChanges() > 0; } public bool Exist(Expression> anyLambda) { return nContext.Set().Any(anyLambda); } public T Find(Expression> whereLambda) { T _entity = nContext.Set().FirstOrDefault(whereLambda); return _entity; } public IQueryable FindList(Expression> whereLamdba, bool isAsc, Expression> orderLamdba) { var _list = nContext.Set().Where(whereLamdba); if