ASP.NET?MVC5?網(wǎng)站開發(fā)框架模型、數(shù)據(jù)存儲(chǔ)、業(yè)務(wù)邏輯(三)
前面項(xiàng)目的層次和調(diào)用關(guān)系都說明了,關(guān)系如下圖
采用三層架構(gòu)的時(shí)候,研究過BLL層的必要性,覺得業(yè)務(wù)邏輯完全可以在controller里實(shí)現(xiàn),沒有必要單獨(dú)做一個(gè)項(xiàng)目,另一個(gè)分層多了會(huì)影響性能。后來我還是把業(yè)務(wù)邏輯獨(dú)立出來,原因如下:
- 業(yè)務(wù)邏輯寫進(jìn)controller里代碼看著比較混亂,時(shí)間久了代碼容易理不清。
- 在controller里直接寫邏輯重復(fù)代碼會(huì)不較多,開發(fā)效率低。
- 分項(xiàng)目有利于代碼重用,有時(shí)候可以直接拿到其他項(xiàng)目中稍作修改就可以用。
對(duì)于性能我覺得分層多了肯定會(huì)有影響,但是不會(huì)很大?,F(xiàn)在硬件的更新速度遠(yuǎn)大于軟件,對(duì)業(yè)務(wù)邏輯處理起來很輕松,多實(shí)例化幾個(gè)類對(duì)性能影響不大。一般來說網(wǎng)站運(yùn)行基本上是一個(gè)存數(shù)據(jù)庫和取數(shù)據(jù)庫的過程,業(yè)務(wù)邏輯還是比較少,只不過現(xiàn)在的網(wǎng)站使用的圖片、動(dòng)畫更多,效果更加絢麗。我覺得網(wǎng)站的效率瓶頸主要出現(xiàn)在服務(wù)器的帶寬、IO性能和存取數(shù)據(jù)庫上。在代碼方面能做的就是優(yōu)化數(shù)據(jù)庫的存取。對(duì)了一般項(xiàng)目來說,為了百分之幾的運(yùn)行效率遠(yuǎn)不如提高開發(fā)效率和更加容易的代碼管理重要,能實(shí)現(xiàn)需求就好,運(yùn)行效率是哪是大牛要做的事。
對(duì)IDAL、DAL、IBLL 、BLL這四個(gè)項(xiàng)目:
IDAL寫一個(gè)Base接口,接口中固定幾個(gè)數(shù)據(jù)庫操作方法,其他接口都繼承自這個(gè)接口;
DAL項(xiàng)目做個(gè)base類實(shí)現(xiàn)這個(gè)IDAL的base接口,其他類都繼承自base類。
同樣IBLL中也寫一個(gè)Base接口,固定幾個(gè)基本的操作方法,同樣其他接口也繼承自這個(gè)base接口
IBLL中也寫一個(gè)base類來實(shí)現(xiàn)IBLL中的base接口,其他類繼承自這個(gè)base類。
這里以對(duì)用戶的操作來構(gòu)建代碼的基本模式:
一、模型
這里寫三個(gè)模型類。打開Ninesk.Models分別添加User、UserGroup、UserConfig三個(gè)模型類。
1、用戶模型—User類
用戶模型或者叫賬戶模型,為什么這么說看下面代碼
using System; using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { /// <summary> /// 用戶模型 /// <remarks> /// 創(chuàng)建: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}個(gè)字符")] [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}個(gè)字符")] [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> /// 用戶狀態(tài)<br /> /// 0正常,1鎖定,2未通過郵件驗(yàn)證,3未通過管理員 /// </summary> public int Status { get; set; } /// <summary> /// 注冊(cè)時(shí)間 /// </summary> public DateTime RegistrationTime { get; set; } /// <summary> /// 上次登陸時(shí)間 /// </summary> public DateTime LoginTime { get; set; } /// <summary> /// 上次登陸IP /// </summary> public DateTime LoginIP { get; set; } public virtual UserGroup Group { get; set; } } }
這個(gè)模型類中只包含用戶名、密碼、用戶組、顯示名、郵箱等屬性,純粹是基本的賬戶信息,目的是讓用戶注冊(cè)的時(shí)候盡可能的少填信息。其他信息如果需要可以再寫新類與賬戶進(jìn)行關(guān)聯(lián),用戶需要的時(shí)候登錄后再進(jìn)行補(bǔ)填(如:資本資料、個(gè)人信息、聯(lián)系方式等。這里先不考慮這些)。這里的顯示名根據(jù)需要可以做昵稱、真實(shí)姓名等來使用。
2、用戶組模型—UserGroup類
這個(gè)類注意下GroupType,這個(gè)用來對(duì)用戶組進(jìn)行一下分類的,方便管理,其實(shí)沒什么特別的意義。我的想法是普通類型就放普通的注冊(cè)用戶的組,如果大的網(wǎng)站允許用戶升級(jí)的話,限定在這個(gè)類型的用戶組內(nèi)。特權(quán)組可以放一些vip之類的用戶組,需要管理員給予,區(qū)別普通用戶組,但又沒有管理權(quán)。管理類型的用戶組需要后臺(tái)管理員給予,可以對(duì)文章、評(píng)論、咨詢進(jìn)行管理。
using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { /// <summary> /// 用戶組 /// <remarks> /// 創(chuàng)建: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}個(gè)字")] [Display(Name="名稱")] public string Name { get; set; } /// <summary> /// 用戶組類型<br /> /// 0普通類型(普通注冊(cè)用戶),1特權(quán)類型(像VIP之類的類型),3管理類型(管理權(quán)限的類型) /// </summary> [Required(ErrorMessage = "必填")] [Display(Name = "用戶組類型")] public int GroupType { get; set; } /// <summary> /// 說明 /// </summary> [Required(ErrorMessage = "必填")] [StringLength(50, ErrorMessage = "少于{0}個(gè)字")] [Display(Name = "說明")] public string Description { get; set; } } }
3、用戶配置模型類—UserConfig類
這個(gè)類是一些用戶配置信息(暫時(shí)只考慮了注冊(cè)設(shè)置),在后臺(tái)管理員處進(jìn)行設(shè)置。
using System.ComponentModel.DataAnnotations; namespace Ninesky.Models { /// <summary> /// 用戶配置 /// <remarks> /// 創(chuàng)建:2014.02.06 /// </remarks> /// </summary> public class UserConfig { [Key] public int ConfigID { get; set; } /// <summary> /// 啟用注冊(cè) /// </summary> [Display(Name = "啟用注冊(cè)")] [Required(ErrorMessage="必填")] public bool Enabled { get; set; } /// <summary> /// 禁止使用的用戶名<br /> /// 用戶名之間用“|”隔開 /// </summary> [Display(Name = "禁止使用的用戶名")] public string ProhibitUserName { get; set; } /// <summary> /// 啟用管理員驗(yàn)證 /// </summary> [Display(Name = "啟用管理員驗(yàn)證")] [Required(ErrorMessage = "必填")] public bool EnableAdminVerify { get; set; } /// <summary> /// 啟用郵件驗(yàn)證 /// </summary> [Display(Name = "啟用郵件驗(yàn)證")] [Required(ErrorMessage = "必填")] public bool EnableEmailVerify { get; set; } /// <summary> /// 默認(rèn)用戶組Id /// </summary> [Display(Name = "默認(rèn)用戶組Id")] [Required(ErrorMessage = "必填")] public int DefaultGroupId { get; set; } } }
二、數(shù)據(jù)存儲(chǔ)層
數(shù)據(jù)存儲(chǔ)層負(fù)責(zé)與數(shù)據(jù)庫打交道,由于使用了接口產(chǎn)生了兩個(gè)項(xiàng)目DAL和IDAL。IDAL是接口項(xiàng)目,DAL是接口的實(shí)現(xiàn)項(xiàng)目。
在與數(shù)據(jù)庫的方便有一些共同的操作,像添加、修改、刪除、查詢等。不想在實(shí)際寫代碼的時(shí)候在用戶類寫一遍這些東西,用戶組類再寫一遍、以后文章、評(píng)論都再重復(fù)寫這些代碼。怎么辦,弄個(gè)基類。以后其他類從基類繼承就把這些公共方法繼承過來了。
1、IDAL項(xiàng)目
首先打開IDAL項(xiàng)目,添加類InterfaceBaseRepository,代碼如下。
using System; using System.Linq; using System.Linq.Expressions; namespace Ninesky.IDAL { /// <summary> /// 接口基類 /// <remarks>創(chuàng)建:2014.02.03 <br /> /// 修改:2014.02.09</remarks> /// </summary> /// <typeparam name="T">類型</typeparam> public interface InterfaceBaseRepository<T> { /// <summary> /// 添加 /// </summary> /// <param name="entity">數(shù)據(jù)實(shí)體</param> /// <returns>添加后的數(shù)據(jù)實(shí)體</returns> T Add(T entity); /// <summary> /// 查詢記錄數(shù) /// </summary> /// <param name="predicate">條件表達(dá)式</param> /// <returns>記錄數(shù)</returns> int Count(Expression<Func<T, bool>> predicate); /// <summary> /// 更新 /// </summary> /// <param name="entity">數(shù)據(jù)實(shí)體</param> /// <returns>是否成功</returns> bool Update(T entity); /// <summary> /// 刪除 /// </summary> /// <param name="entity">數(shù)據(jù)實(shí)體</param> /// <returns>是否成功</returns> bool Delete(T entity); /// <summary> /// 是否存在 /// </summary> /// <param name="anyLambda">查詢表達(dá)式</param> /// <returns>布爾值</returns> bool Exist(Expression<Func<T, bool>> anyLambda); /// <summary> /// 查詢數(shù)據(jù) /// </summary> /// <param name="whereLambda">查詢表達(dá)式</param> /// <returns>實(shí)體</returns> T Find(Expression<Func<T, bool>> whereLambda); /// <summary> /// 查找數(shù)據(jù)列表 /// </summary> /// <typeparam name="S">排序</typeparam> /// <param name="whereLamdba">查詢表達(dá)式</param> /// <param name="isAsc">是否升序</param> /// <param name="orderLamdba">排序表達(dá)式</param> /// <returns></returns> IQueryable<T> FindList<S>(Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba); /// <summary> /// 查找分頁數(shù)據(jù)列表 /// </summary> /// <typeparam name="S">排序</typeparam> /// <param name="pageIndex">當(dāng)前頁</param> /// <param name="pageSize">每頁記錄數(shù)</param> /// <param name="totalRecord">總記錄數(shù)</param> /// <param name="whereLamdba">查詢表達(dá)式</param> /// <param name="isAsc">是否升序</param> /// <param name="orderLamdba">排序表達(dá)式</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個(gè)公共方法。這幾個(gè)方法基本滿足一般需要,特殊的方法在繼承的時(shí)候再添加。
還使用了泛型,在繼承的時(shí)候傳入實(shí)體類型就可以直接繼承這些方法了。具體看下InterfaceUserRepository接口就清楚了。
using Ninesky.Models; namespace Ninesky.IDAL { /// <summary> /// 用戶接口 /// <remarks>創(chuàng)建:2014.02.03</remarks> /// </summary> public interface InterfaceUserRepository:InterfaceBaseRepository<User> { } }
簡(jiǎn)單吧,繼承自InterfaceBaseRepository接口并傳入實(shí)體類User就行了。我們?cè)陬愐晥D中看下,是不是繼承了基類的接口。
2、DAL項(xiàng)目
DAL項(xiàng)目是對(duì)IDAL項(xiàng)目接口的實(shí)現(xiàn),項(xiàng)目中要?jiǎng)?chuàng)建DbContext類,對(duì)于DbContext類很多人討論過它對(duì)數(shù)據(jù)庫存取的效率,MSDN中說其是輕量的, 創(chuàng)建不需要很大開銷,它也不是線程安全的對(duì)象,并且具有數(shù)據(jù)容器的性質(zhì)(跟蹤),因此很多人認(rèn)為不應(yīng)該將其靜態(tài)化、單例化。但是對(duì)用戶的單次請(qǐng)求來說實(shí)現(xiàn)DbContext唯一是合理的。 先看代碼吧,非常簡(jiǎn)單。
using Ninesky.Models; using System.Data.Entity; namespace Ninesky.DAL { /// <summary> /// 數(shù)據(jù)上下文 /// <remarks>創(chuàng)建: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") { } } }
下面創(chuàng)建一個(gè)BaseRepository類,繼承自InterfaceBaseRepository并實(shí)現(xiàn)類其接口的方法。
using Ninesky.IDAL; using System; using System.Linq; using System.Linq.Expressions; namespace Ninesky.DAL { /// <summary> /// 倉儲(chǔ)基類 /// <remarks>創(chuàng)建: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; } } }
代碼中都是對(duì)數(shù)據(jù)庫的操作。比較有看頭的是這句protected NineskyDbContext nContext = ContextFactory.GetCurrentContext();
ContextFactory是一個(gè)簡(jiǎn)單工廠類,GetCurrentContext()是一個(gè)靜態(tài)函數(shù)。利用簡(jiǎn)單工廠獲取請(qǐng)求內(nèi)的當(dāng)前DbContext,也就是請(qǐng)求內(nèi)的DbContext單例。先添加一個(gè)工廠類ContextFactory
using System.Data.Entity; using System.Runtime.Remoting.Messaging; namespace Ninesky.DAL { /// <summary> /// 上下文簡(jiǎn)單工廠 /// <remarks> /// 創(chuàng)建:2014.02.05 /// </remarks> /// </summary> public class ContextFactory { /// <summary> /// 獲取當(dāng)前數(shù)據(jù)上下文 /// </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,如果為空則初始化一個(gè)NineskyContext,如果存在則直接返回??碈allContext,MSDN中講CallContext提供對(duì)每個(gè)邏輯執(zhí)行線程都唯一的數(shù)據(jù)槽,而在WEB程序里,每一個(gè)請(qǐng)求恰巧就是一個(gè)邏輯線程所以可以使用CallContext來實(shí)現(xiàn)單個(gè)請(qǐng)求之內(nèi)的DbContext單例。
下面添加具體的倉儲(chǔ)代碼。
在DAL中再添加一個(gè)UserRepository類,繼承自BaseRepository和InterfaceUserRepository。目的是繼承自BaseRepository類,實(shí)現(xiàn)InterfaceUserRepositor接口。
using Ninesky.IDAL; using Ninesky.Models; using System.Linq; namespace Ninesky.DAL { /// <summary> /// 用戶倉庫 /// <remarks>創(chuàng)建:2014.02.03</remarks> /// </summary> class UserRepository: BaseRepository<User>, InterfaceUserRepository { } }
UserRepository就直接繼承了基類中的方法,基類中的方法能滿足絕大部分需要,UserRepository就不用再增加函數(shù)了,其他Repository類都類似,不在貼代碼了。
這里我們?cè)诮ㄒ粋€(gè)Repository工廠,用來返回項(xiàng)目中的所有Repository類。
using Ninesky.IDAL; namespace Ninesky.DAL { /// <summary> /// 簡(jiǎn)單工廠? /// <remarks>創(chuàng)建:2014.02.03</remarks> /// </summary> public static class RepositoryFactory { /// <summary> /// 用戶倉儲(chǔ) /// </summary> public static InterfaceUserRepository UserRepository { get { return new UserRepository(); } } } }
以后在BLL中調(diào)用的時(shí)候就不用每次都寫InterfaceUserRepository _iUserRsy = new UserRepository()了,直接寫成InterfaceUserRepository _iUserRsy = RepositoryFactory.UserRepository這個(gè)東西的好處就是,以后在DAL項(xiàng)目中實(shí)現(xiàn)InterfaceUserRepository接口的類需要修改時(shí)我們可以直接創(chuàng)建個(gè)新類,然后RepositoryFactory類中讓UserRepository屬性返回新類就行了。
3、IBLL項(xiàng)目
IBLL是業(yè)務(wù)邏輯層的接口,業(yè)務(wù)邏輯層對(duì)數(shù)據(jù)庫的操作上基本還是增、刪、改。同樣寫一個(gè)基接口把這三個(gè)操作寫進(jìn)去,這里與IDAL思路類似。
namespace Ninesky.IBLL { /// <summary> /// 接口基類 /// <remarks>創(chuàng)建:2014.02.03</remarks> /// </summary> public interface InterfaceBaseService<T> where T : class { /// <summary> /// 添加 /// </summary> /// <param name="entity">數(shù)據(jù)實(shí)體</param> /// <returns>添加后的數(shù)據(jù)實(shí)體</returns> T Add(T entity); /// <summary> /// 更新 /// </summary> /// <param name="entity">數(shù)據(jù)實(shí)體</param> /// <returns>是否成功</returns> bool Update(T entity); /// <summary> /// 刪除 /// </summary> /// <param name="entity">數(shù)據(jù)實(shí)體</param> /// <returns>是否成功</returns> bool Delete(T entity); } }
在添加一個(gè)InterfaceUserService接口,繼承自InterfaceBaseService。根據(jù)需要在接口中又添加了幾個(gè)方法。在這里對(duì)Find方法的名稱進(jìn)行統(tǒng)一,凡是返回實(shí)體類的名稱為Find()或FindByXXX(),返回一組數(shù)據(jù)的方法名稱為FindList()或FindXXXList,分頁的名稱格式為FindPageList()或FindxxxPageList()
using Ninesky.Models; using System.Linq; namespace Ninesky.IBLL { /// <summary> /// 用戶相關(guān)接口 /// <remarks> /// 創(chuàng)建: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">頁碼數(shù)</param> /// <param name="pageSize">每頁記錄數(shù)</param> /// <param name="totalRecord">總記錄數(shù)</param> /// <param name="order">排序:0-ID升序(默認(rèn)),1ID降序,2注冊(cè)時(shí)間升序,3注冊(cè)時(shí)間降序,4登錄時(shí)間升序,5登錄時(shí)間降序</param> /// <returns></returns> IQueryable<User> FindPageList(int pageIndex, int pageSize, out int totalRecord,int order); } }
4、BLL項(xiàng)目
BLL項(xiàng)目中要實(shí)現(xiàn)InterfaceUserService接口的方法,先添加BaseService的
using Ninesky.IBLL; using Ninesky.IDAL; namespace Ninesky.BLL { /// <summary> /// 服務(wù)基類 /// <remarks>創(chuàng)建: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); } } }
這個(gè)類的構(gòu)造函數(shù)中要傳入一個(gè)參數(shù)就是currentRepository 這個(gè)在繼承的時(shí)候進(jìn)行傳入。這里還是看用戶類。
using Ninesky.DAL; using Ninesky.IBLL; using Ninesky.Models; using System.Linq; namespace Ninesky.BLL { /// <summary> /// 用戶服務(wù)類 /// <remarks> /// 創(chuàng)建: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); } } } }
上面這個(gè)FindPageList代碼太累贅了,一時(shí)還沒想到好方法。
5、總結(jié)
今天寫到這里還是在想項(xiàng)目間的調(diào)用實(shí)現(xiàn),寫了兩個(gè)base接口、兩個(gè)base類,以后其他的類都從它們繼承,寫法都很類似。下次可以開始做界面了,在Ninesky.Web項(xiàng)目中基本上是通過IBLL,BLL跟數(shù)據(jù)進(jìn)行打交道了。
FindPageList() 這個(gè)排序的方法確實(shí)不太通用,代碼修改如下:
1、接口 InterfaceBaseRepository
修改兩個(gè)接口方法如圖紅框部分。
image
2、BaseRepository類
添加OrderBy方法,代碼如下:
/// <summary> /// 排序 /// </summary> /// <typeparam name="T">類型</typeparam> /// <param name="source">原IQueryable</param> /// <param name="propertyName">排序?qū)傩悦?lt;/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 3、修改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); }
以上就是ASP.NET MVC5 網(wǎng)站開發(fā)框架模型、數(shù)據(jù)存儲(chǔ)以及業(yè)務(wù)邏輯的相關(guān)介紹,比之前兩節(jié)的內(nèi)容是不是更加豐富了,希望本文可以對(duì)大家的學(xué)習(xí)有所幫助。
相關(guān)文章
asp.net中引用同一個(gè)項(xiàng)目中的類庫 避免goToDefinition時(shí)不能到達(dá)真正的定義類
asp.net中引用同一個(gè)項(xiàng)目中的類庫 避免 goToDefinition時(shí)不能到達(dá)真正的定義類2011-10-10Asp.Net防止刷新重復(fù)提交數(shù)據(jù)的辦法
最近在用Asp.Net編寫點(diǎn)東西時(shí)遇到個(gè)問題:即用戶在提交表單后按刷新就會(huì)重復(fù)提交數(shù)據(jù),即所謂的“刷新重復(fù)提交”的問題。2013-03-03記錄游客頁面訪問IP的簡(jiǎn)易實(shí)現(xiàn)代碼 (asp.net+txt)
記錄游客頁面訪問IP的簡(jiǎn)易實(shí)現(xiàn) (asp.net for notepad)2010-01-01