ASP.NET MVC5 网站开发实践(一) - 框架(续) 模型、数据存储、业务逻辑

上次搭建好了项目框架,但仍是以为不太对劲,后来才想起来没有对开发目标进行定位,这个小demo虽然不用作需求分析,可是要实现什么效果还得明确。后来想了一下就作个最简单的网站,目标定为小公司进行展现用的网站。功能有显示用的文章功能(新闻、产品展现、公司介绍等),咨询留言,评论等,另外还包括用户管理,网站设置这两个部分,算是个极简的网站吧。html

目录:

ASP.NET MVC5 网站开发实践 - 概述数据库

ASP.NET MVC5 网站开发实践(一) - 项目框架安全

 

 

前面项目的层次和调用关系都说明了,关系以下图服务器

image

采用三层架构的时候,在群里跟 @盛开生命 讨论过BLL层的必要性,以为业务逻辑彻底能够在controller里实现,没有必要单独作一个项目,另外一个分层多了会影响性能。后来我仍是把业务逻辑独立出来,缘由以下:架构

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

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

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

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

DAL项目作个base类实现这个IDAL的base接口,其余类都继承自base类。性能

一样IBLL中也写一个Base接口,固定几个基本的操做方法,一样其余接口也继承自这个base接口优化

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

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

1、模型

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

一、用户模型—User类

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

using System;
using System.ComponentModel.DataAnnotations;

namespace Ninesky.Models
{
    /// <summary>
    /// 用户模型
    /// <remarks>
    /// 建立:2014.02.02<br />
    /// 修改:2014.02.05
    /// </remarks>
    /// </summary>
    public class User
    {
        [Key]
        public int UserID { get; set; }

        /// <summary>
        /// 用户名
        /// </summary>
        [Required(ErrorMessage="必填")]
        [StringLength(20,MinimumLength=4,ErrorMessage="{1}到{0}个字符")]
        [Display(Name="用户名")]
        public string UserName { get; set; }

        /// <summary>
        /// 用户组ID
        /// </summary>
        [Required(ErrorMessage = "必填")]
        [Display(Name = "用户组ID")]
        public int GroupID { get; set; }

        /// <summary>
        /// 显示名
        /// </summary>
        [Required(ErrorMessage = "必填")]
        [StringLength(20, MinimumLength = 2, ErrorMessage = "{1}到{0}个字符")]
        [Display(Name = "显示名")]
        public string DisplayName { get; set; }

        /// <summary>
        /// 密码
        /// </summary>
        [Required(ErrorMessage = "必填")]
        [Display(Name = "密码")]
        [DataType(DataType.Password)]
        public string Password { get; set; }

        /// <summary>
        /// 邮箱
        /// </summary>
        [Required(ErrorMessage = "必填")]
        [Display(Name = "邮箱")]
        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }

        /// <summary>
        /// 用户状态<br />
        /// 0正常,1锁定,2未经过邮件验证,3未经过管理员
        /// </summary>
        public int Status { get; set; }

        /// <summary>
        /// 注册时间
        /// </summary>
        public DateTime RegistrationTime { get; set; }

        /// <summary>
        /// 上次登录时间
        /// </summary>
        public DateTime LoginTime { get; set; }

        /// <summary>
        /// 上次登录IP
        /// </summary>
        public DateTime LoginIP { get; set; }

        public virtual UserGroup Group { get; set; }

    }
}

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

二、用户组模型—UserGroup类

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

using System.ComponentModel.DataAnnotations;

namespace Ninesky.Models
{
    /// <summary>
    /// 用户组
    /// <remarks>
    /// 建立:2014.02.02
    /// 修改:2014.02.08
    /// </remarks>
    /// </summary>
    public class UserGroup
    {
        [Key]
        public int GroupID { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        [Required(ErrorMessage="必填")]
        [StringLength(20, MinimumLength = 2, ErrorMessage = "{1}到{0}个字")]
        [Display(Name="名称")]
        public string Name { get; set; }

        /// <summary>
        /// 用户组类型<br />
        /// 0普通类型(普通注册用户),1特权类型(像VIP之类的类型),3管理类型(管理权限的类型)
        /// </summary>
        [Required(ErrorMessage = "必填")]
        [Display(Name = "用户组类型")]
        public int GroupType { get; set; }

        /// <summary>
        /// 说明
        /// </summary>
        [Required(ErrorMessage = "必填")]
        [StringLength(50, ErrorMessage = "少于{0}个字")]
        [Display(Name = "说明")]
        public string Description { get; set; }
    }
}

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

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

using System.ComponentModel.DataAnnotations;

namespace Ninesky.Models
{
    /// <summary>
    /// 用户配置
    /// <remarks>
    /// 建立:2014.02.06
    /// </remarks>
    /// </summary>
    public class UserConfig
    {
        [Key]
        public int ConfigID { get; set; }

        /// <summary>
        /// 启用注册
        /// </summary>
        [Display(Name = "启用注册")]
        [Required(ErrorMessage="必填")]
        public bool Enabled { get; set; }

        /// <summary>
        /// 禁止使用的用户名<br />
        /// 用户名之间用“|”隔开
        /// </summary>
        [Display(Name = "禁止使用的用户名")]
        public string ProhibitUserName { get; set; }

        /// <summary>
        /// 启用管理员验证
        /// </summary>
        [Display(Name = "启用管理员验证")]
        [Required(ErrorMessage = "必填")]
        public bool EnableAdminVerify { get; set; }

        /// <summary>
        /// 启用邮件验证
        /// </summary>
        [Display(Name = "启用邮件验证")]
        [Required(ErrorMessage = "必填")]
        public bool EnableEmailVerify { get; set; }

        /// <summary>
        /// 默认用户组Id
        /// </summary>
        [Display(Name = "默认用户组Id")]
        [Required(ErrorMessage = "必填")]
        public int DefaultGroupId { get; set; }
    }
}

2、数据存储层

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

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

一、IDAL项目

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

using System;
using System.Linq;
using System.Linq.Expressions;

namespace Ninesky.IDAL
{
    /// <summary>
    /// 接口基类
    /// <remarks>建立:2014.02.03 <br />
    /// 修改:2014.02.09</remarks>
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    public interface InterfaceBaseRepository<T>
    {
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="entity">数据实体</param>
        /// <returns>添加后的数据实体</returns>
        T Add(T entity);

        /// <summary>
        /// 查询记录数
        /// </summary>
        /// <param name="predicate">条件表达式</param>
        /// <returns>记录数</returns>
        int Count(Expression<Func<T, bool>> predicate);

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entity">数据实体</param>
        /// <returns>是否成功</returns>
        bool Update(T entity);

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="entity">数据实体</param>
        /// <returns>是否成功</returns>
        bool Delete(T entity);

        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="anyLambda">查询表达式</param>
        /// <returns>布尔值</returns>
        bool Exist(Expression<Func<T, bool>> anyLambda);

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="whereLambda">查询表达式</param>
        /// <returns>实体</returns>
        T Find(Expression<Func<T, bool>> whereLambda);

        /// <summary>
        /// 查找数据列表
        /// </summary>
        /// <typeparam name="S">排序</typeparam>
        /// <param name="whereLamdba">查询表达式</param>
        /// <param name="isAsc">是否升序</param>
        /// <param name="orderLamdba">排序表达式</param>
        /// <returns></returns>
        IQueryable<T> FindList<S>(Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba);
        
        /// <summary>
        /// 查找分页数据列表
        /// </summary>
        /// <typeparam name="S">排序</typeparam>
        /// <param name="pageIndex">当前页</param>
        /// <param name="pageSize">每页记录数</param>
        /// <param name="totalRecord">总记录数</param>
        /// <param name="whereLamdba">查询表达式</param>
        /// <param name="isAsc">是否升序</param>
        /// <param name="orderLamdba">排序表达式</param>
        /// <returns></returns>
        IQueryable<T> FindPageList<S>(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba);

    }
}
这里定义了增、删、改、判断存在、返回模型的查询、返回集合的查询,返回分页集合的查询7个公共方法。这几个方法基本知足通常须要,特殊的方法在继承的时候再添加。

还使用了泛型,在继承的时候传入实体类型就能够直接继承这些方法了。具体看下InterfaceUserRepository接口就清楚了。

using Ninesky.Models;
namespace Ninesky.IDAL
{
    /// <summary>
    /// 用户接口
    /// <remarks>建立:2014.02.03</remarks>
    /// </summary>
    public interface InterfaceUserRepository:InterfaceBaseRepository<User>
    {
    }
}

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

image

二、DAL项目

DAL项目是对IDAL项目接口的实现,项目中要建立DbContext类,对于DbContext类不少人讨论过它对数据库存取的效率,MSDN中说其是轻量的, 建立不须要很大开销,它也不是线程安全的对象,而且具备数据容器的性质(跟踪),所以不少人认为不该该将其静态化、单例化。可是对用户的单次请求来讲实现DbContext惟一是合理的。 先看代码吧,很是简单。

using Ninesky.Models;
using System.Data.Entity;

namespace Ninesky.DAL
{
    /// <summary>
    /// 数据上下文
    /// <remarks>建立:2014.02.03</remarks>
    /// </summary>
    public class NineskyDbContext:DbContext
    {
        public DbSet<User> Users { get; set; }
        public DbSet<UserGroup> UserGroups { get; set; }
        public DbSet<UserConfig> UserConfig { get; set; }
        public NineskyDbContext()
            : base("DefaultConnection")
        {
        }
    }
}

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

using Ninesky.IDAL;
using System;
using System.Linq;
using System.Linq.Expressions;

namespace Ninesky.DAL
{
    /// <summary>
    /// 仓储基类
    /// <remarks>建立:2014.02.03</remarks>
    /// </summary>
    public class BaseRepository<T>: InterfaceBaseRepository<T> where T : class 
    {
        protected NineskyDbContext nContext = ContextFactory.GetCurrentContext();

        public T Add(T entity)
        {
            nContext.Entry<T>(entity).State = System.Data.Entity.EntityState.Added;
            nContext.SaveChanges();
            return entity;
        }

        public int Count(Expression<Func<T, bool>> predicate)
        {
            return nContext.Set<T>().Count(predicate);
        }

        public bool Update(T entity)
        {
            nContext.Set<T>().Attach(entity);
            nContext.Entry<T>(entity).State = System.Data.Entity.EntityState.Modified;
            return nContext.SaveChanges() > 0;
        }

        public bool Delete(T entity)
        {
            nContext.Set<T>().Attach(entity);
            nContext.Entry<T>(entity).State = System.Data.Entity.EntityState.Deleted;
            return nContext.SaveChanges() > 0;
        }

        public bool Exist(Expression<Func<T, bool>> anyLambda)
        {
            return nContext.Set<T>().Any(anyLambda);
        }

        public T Find(Expression<Func<T, bool>> whereLambda)
        {
            T _entity = nContext.Set<T>().FirstOrDefault<T>(whereLambda);
            return _entity;
        }

        public IQueryable<T> FindList<S>(Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba)
        {
            var _list = nContext.Set<T>().Where<T>(whereLamdba);
            if (isAsc) _list = _list.OrderBy<T, S>(orderLamdba);
            else _list = _list.OrderByDescending<T, S>(orderLamdba);
            return _list;
        }

        public IQueryable<T> FindPageList<S>(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba)
        {
            var _list = nContext.Set<T>().Where<T>(whereLamdba);
            totalRecord = _list.Count();
            if (isAsc) _list = _list.OrderBy<T, S>(orderLamdba).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
            else _list = _list.OrderByDescending<T, S>(orderLamdba).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
            return _list;
        }
    }
}

代码中都是对数据库的操做。比较有看头的是这句protected NineskyDbContext nContext = ContextFactory.GetCurrentContext();

ContextFactory是一个简单工厂类,GetCurrentContext()是一个静态函数。利用简单工厂获取请求内的当前DbContext,也就是请求内的DbContext单例。先添加一个工厂类ContextFactory

using System.Data.Entity;
using System.Runtime.Remoting.Messaging;

namespace Ninesky.DAL
{
    /// <summary>
    /// 上下文简单工厂
    /// <remarks>
    /// 建立:2014.02.05
    /// </remarks>
    /// </summary>
    public class ContextFactory
    {

        /// <summary>
        /// 获取当前数据上下文
        /// </summary>
        /// <returns></returns>
        public static NineskyDbContext GetCurrentContext()
        {
            NineskyDbContext _nContext = CallContext.GetData("NineskyContext") as NineskyDbContext;
            if (_nContext == null)
            {
                _nContext = new NineskyDbContext();
                CallContext.SetData("NineskyContext", _nContext);
            }
            return _nContext;
        }
    }
}

这里是先在CallContext中获取NineskyContext,若是为空则初始化一个NineskyContext,若是存在则直接返回。看CallContext,MSDN中讲CallContext提供对每一个逻辑执行线程都惟一的数据槽,而在WEB程序里,每个请求恰巧就是一个逻辑线程因此可使用CallContext来实现单个请求以内的DbContext单例。

下面添加具体的仓储代码。

在DAL中再添加一个UserRepository类,继承自BaseRepository和InterfaceUserRepository。目的是继承自BaseRepository类,实现InterfaceUserRepositor接口。

using Ninesky.IDAL;
using Ninesky.Models;
using System.Linq;

namespace Ninesky.DAL
{
    /// <summary>
    /// 用户仓库
    /// <remarks>建立:2014.02.03</remarks>
    /// </summary>
    class UserRepository: BaseRepository<User>, InterfaceUserRepository
    {
    }
}

UserRepository就直接继承了基类中的方法,基类中的方法能知足绝大部分须要,UserRepository就不用再增长函数了,其余Repository类都相似,不在贴代码了。

这里咱们在建一个Repository工厂,用来返回项目中的全部Repository类。

using Ninesky.IDAL;

namespace Ninesky.DAL
{
    /// <summary>
    /// 简单工厂?
    /// <remarks>建立:2014.02.03</remarks>
    /// </summary>
    public static class RepositoryFactory
    {
        /// <summary>
        /// 用户仓储
        /// </summary>
        public static InterfaceUserRepository UserRepository { get { return new UserRepository(); } }
    }
}

之后在BLL中调用的时候就不用每次都写InterfaceUserRepository _iUserRsy = new  UserRepository()了,直接写成InterfaceUserRepository _iUserRsy = RepositoryFactory.UserRepository这个东西的好处就是,之后在DAL项目中实现InterfaceUserRepository接口的类须要修改时咱们能够直接建立个新类,而后RepositoryFactory类中让UserRepository属性返回新类就好了。

三、IBLL项目

IBLL是业务逻辑层的接口,业务逻辑层对数据库的操做上基本仍是增、删、改。一样写一个基接口把这三个操做写进去,这里与IDAL思路相似。

namespace Ninesky.IBLL
{
    /// <summary>
    /// 接口基类
    /// <remarks>建立:2014.02.03</remarks>
    /// </summary>
    public interface InterfaceBaseService<T> where T : class
    {
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="entity">数据实体</param>
        /// <returns>添加后的数据实体</returns>
        T Add(T entity);

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entity">数据实体</param>
        /// <returns>是否成功</returns>
        bool Update(T entity);

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="entity">数据实体</param>
        /// <returns>是否成功</returns>
        bool Delete(T entity);
    }
}

在添加一个InterfaceUserService接口,继承自InterfaceBaseService。根据须要在接口中又添加了几个方法。在这里对Find方法的名称进行统一,凡是返回实体类的名称为Find()或FindByXXX(),返回一组数据的方法名称为FindList()或FindXXXList,分页的名称格式为FindPageList()或FindxxxPageList()

using Ninesky.Models;
using System.Linq;

namespace Ninesky.IBLL
{
    /// <summary>
    /// 用户相关接口
    /// <remarks>
    /// 建立:2014.02.09
    /// </remarks>
    /// </summary>
    public interface InterfaceUserService:InterfaceBaseService<User>
    {

        /// <summary>
        /// 用户是否存在
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <returns>布尔值</returns>
        bool Exist(string userName);

        /// <summary>
        /// 查找用户
        /// </summary>
        /// <param name="userID">用户ID</param>
        /// <returns></returns>
        User Find(int userID);

        /// <summary>
        /// 查找用户
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <returns></returns>
        User Find(string userName);

        /// <summary>
        /// 用户列表
        /// </summary>
        /// <param name="pageIndex">页码数</param>
        /// <param name="pageSize">每页记录数</param>
        /// <param name="totalRecord">总记录数</param>
        /// <param name="order">排序:0-ID升序(默认),1ID降序,2注册时间升序,3注册时间降序,4登陆时间升序,5登陆时间降序</param>
        /// <returns></returns>
        IQueryable<User> FindPageList(int pageIndex, int pageSize, out int totalRecord,int order);
    }
}
四、BLL项目

BLL项目中要实现InterfaceUserService接口的方法,先添加BaseService的

using Ninesky.IBLL;
using Ninesky.IDAL;

namespace Ninesky.BLL
{
    /// <summary>
    /// 服务基类
    /// <remarks>建立:2014.02.03</remarks>
    /// </summary>
    public abstract class BaseService<T> : InterfaceBaseService<T> where T : class
    {
        protected InterfaceBaseRepository<T> CurrentRepository { get; set; }

        public BaseService(InterfaceBaseRepository<T> currentRepository) { CurrentRepository = currentRepository; }

        public T Add(T entity) { return CurrentRepository.Add(entity); }

        public bool Update(T entity) { return CurrentRepository.Update(entity); }

        public bool Delete(T entity) { return CurrentRepository.Delete(entity); }
    }
}

这个类的构造函数中要传入一个参数就是currentRepository 这个在继承的时候进行传入。这里仍是看用户类。

using Ninesky.DAL;
using Ninesky.IBLL;
using Ninesky.Models;
using System.Linq;

namespace Ninesky.BLL
{
    /// <summary>
    /// 用户服务类
    /// <remarks>
    /// 建立:2014.02.12
    /// </remarks>
    /// </summary>
    public class UserService:BaseService<User>,InterfaceUserService
    {
        public UserService() : base(RepositoryFactory.UserRepository) { }

        public bool Exist(string userName) { return CurrentRepository.Exist(u => u.UserName == userName);}

        public User Find(int userID) { return CurrentRepository.Find(u => u.UserID == userID); }

        public User Find(string userName) { return CurrentRepository.Find(u => u.UserName == userName); }

        public IQueryable<User> FindPageList(int pageIndex, int pageSize, out int totalRecord, int order)
        {
            switch(order)
            {
                case 0: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u => true, true, u => u.UserID);
                case 1: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u => true, false, u => u.UserID);
                case 2: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u => true, true, u => u.RegistrationTime);
                case 3: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u => true, false, u => u.RegistrationTime);
                case 4: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u => true, true, u => u.LoginTime);
                case 5: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u => true, false, u => u.LoginTime);
                default: return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u => true, true, u => u.UserID);
            }
            
        }
    }
}

上面这个FindPageList代码太累赘了,一时还没想到好方法。

五、总结

今天写到这里仍是在想项目间的调用实现,写了两个base接口、两个base类,之后其余的类都从它们继承,写法都很相似。下次能够开始作界面了,在Ninesky.Web项目中基本上是经过IBLL,BLL跟数据进行打交道了。

 

===================================================

FindPageList() 这个排序的方法确实不太通用,参考@jingming290 提供的代码修改以下:

一、接口 InterfaceBaseRepository

修改两个接口方法如图红框部分。

image

二、BaseRepository类

添加OrderBy方法,代码以下:

/// <summary>
        /// 排序
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="source">原IQueryable</param>
        /// <param name="propertyName">排序属性名</param>
        /// <param name="isAsc">是否正序</param>
        /// <returns>排序后的IQueryable<T></returns>
        private IQueryable<T> OrderBy(IQueryable<T> source, string propertyName, bool isAsc)
        {
            if (source == null) throw new ArgumentNullException("source", "不能为空");
            if (string.IsNullOrEmpty(propertyName)) return source;
            var _parameter = Expression.Parameter(source.ElementType);
            var _property = Expression.Property(_parameter, propertyName);
            if (_property == null) throw new ArgumentNullException("propertyName", "属性不存在");
            var _lambda = Expression.Lambda(_property, _parameter);
            var _methodName = isAsc ? "OrderBy" : "OrderByDescending";
            var _resultExpression = Expression.Call(typeof(Queryable), _methodName, new Type[] { source.ElementType, _property.Type }, source.Expression, Expression.Quote(_lambda));
            return source.Provider.CreateQuery<T>(_resultExpression);
        }

修改FindList和FindPageList方法,修改下图

image

三、修改UserService的FindPageList方法

修改后的代码以下:

public IQueryable<User> FindPageList(int pageIndex, int pageSize, out int totalRecord, int order)
        {
            bool _isAsc = true;
            string _orderName = string.Empty;
            switch(order)
            {
                case 0:
                    _isAsc = true;
                    _orderName = "UserID";
                    break;
                case 1:
                    _isAsc = false;
                    _orderName = "UserID";
                    break;
                case 2: 
                    _isAsc = true;
                    _orderName = "RegistrationTime";
                    break;
                case 3: 
                    _isAsc = false;
                    _orderName = "RegistrationTime";
                    break;
                case 4: 
                    _isAsc = true;
                    _orderName = "LoginTime";
                    break;
                case 5: _isAsc = false;
                    _orderName = "LoginTime";
                    break;
                default: 
                    _isAsc = false;
                    _orderName = "UserID";
                    break;
            }
            return CurrentRepository.FindPageList(pageIndex, pageSize, out totalRecord, u => true, _orderName, _isAsc);
        }

感谢@jingming290

相关文章
相关标签/搜索