Asp.net MVC 搭建属于自己的框架(一)

为什么要自己搭框架?

  大家伙别急,让我慢慢地告诉你!大家有没有这种感觉,从一家跳槽到另一家公司,公司的框架往往是不相同的,这样你必须就得摒弃原来的,学习新的框架。

问题是你用习惯了一种框架,比如封装的扩展方法、工厂模式、实体映射等等,你用得很爽,但是跳槽到新的公司,又得学习他们公司的框架,往往你在这上面

要花费不少时间。

所以我才有了搭建自己的框架的想法,我的框架用到了EntityFramework6.0+Asp.NET MVC4+Autofac等,下面是我的框架结构:

 

MyFrame.Domain 实体模型层

MyFrame.DataMapping 数据映射层:映射实体类和数据库表关系,数据库上下文存放在该层

MyFrame.IDao 数据访问接口层

MyFrame.Dao 数据访问层

MyFrame.IService 业务逻辑接口层

MyFrame.Service 业务逻辑层

MyFrame.Common 通用扩展层

MyFrame.Web UI层

层与层之间的引用关系

  Domain(最低层)=》每个层调用;IDao=>Dao,Service; IService=>Service ; IDao,IService=>Web

实体基类
  MyFrame.Domain.DomainBase:实体基类,实体类都需要继承DomainBase,现在这个类只有两个属性,等之后慢慢扩展完善  

 1 using System;
 2 
 3 namespace MyFrame.Domain
 4 {
 5     /// <summary>
 6     /// 实体基类
 7     /// </summary>
 8     public class DomainBase
 9     {
10         /// <summary>
11         /// 编号
12         /// </summary>
13         public int Id { get; set; }
14 
15         /// <summary>
16         /// 创建时间
17         /// </summary>
18         public DateTime CreateTime { get; set; }
19     }
20 }
DomainBase

数据访问基类接口 

MyFrame.IDao.IDaoBase:封装了增删改查方法以及分页等

 1 using System.Collections.Generic;
 2 using PagedList;
 3 
 4 namespace MyFrame.IDao
 5 {
 6     /// <summary>
 7     /// 数据访问层的基类接口
 8     /// </summary>
 9     public interface IDaoBase<T> where T:class 
10     {
11         /// <summary>
12         /// 增加
13         /// </summary>
14         /// <param name="domain">实体</param>
15         /// <returns></returns>
16         int Insert(T domain);
17 
18         /// <summary>
19         /// 通过Id删除
20         /// </summary>
21         /// <param name="id">Id</param>
22         /// <returns></returns>
23         bool Delete(int id);
24 
25         /// <summary>
26         /// 删除
27         /// </summary>
28         /// <param name="domain">实体</param>
29         /// <returns></returns>
30         bool Delete(T domain);
31 
32         /// <summary>
33         /// 更新操作
34         /// </summary>
35         /// <param name="domain">实体</param>
36         /// <returns></returns>
37         bool Update(T domain);
38 
39         /// <summary>
40         /// 通过Id查询
41         /// </summary>
42         /// <param name="id">Id</param>
43         /// <returns></returns>
44         T SelectById(int id);
45 
46         /// <summary>
47         /// 查询所有
48         /// </summary>
49         /// <returns></returns>
50         IEnumerable<T> SelectAll();
51 
52         /// <summary>
53         /// 分页查询
54         /// </summary>
55         /// <typeparam name="T"></typeparam>
56         /// <param name="pageIndex"></param>
57         /// <param name="pageSize"></param>
58         /// <returns></returns>
59         IPagedList<T> SelectPageList(int? pageIndex = 1, int? pageSize = 10);
60     }
61 }
IDaoBase

数据访问实现基类

MyFrame.Dao.DaoBase:需要继承IDaoBase,IDisposable

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Data.Entity;
  4 using System.Linq;
  5 using MyFrame.Domain;
  6 using MyFrame.IDao;
  7 using MyFrame.DataMapping;
  8 using PagedList;
  9 
 10 namespace MyFrame.Dao
 11 {
 12     /// <summary>
 13     /// 数据访问层基类
 14     /// </summary>
 15     public class DaoBase<T>  : IDisposable, IDaoBase<T> where T : DomainBase 
 16     {
 17         protected readonly DbContext DbContext;
 18 
 19         public DaoBase()
 20         {
 21             DbContext = new DataBaseContext();
 22         }
 23 
 24         public  int Insert(T t)
 25         {
 26             t.CreateTime = DateTime.Now;
 27             DbContext.Entry<T>(t);
 28             DbContext.Set<T>().Add(t);
 29             return SaveChanges();
 30         }
 31 
 32         public bool Delete(int id)
 33         {
 34             T domain = DbContext.Set<T>().FirstOrDefault(s => s.Id == id);
 35             if (domain == null)
 36                 return false;
 37             DbContext.Set<T>().Attach(domain);
 38             DbContext.Set<T>().Remove(domain);
 39             return SaveChanges() > 0;
 40         }
 41 
 42         public bool Delete(T t)
 43         {
 44             DbContext.Set<T>().Attach(t);
 45             DbContext.Set<T>().Remove(t);
 46             return SaveChanges() > 0;
 47         }
 48 
 49         public bool Update(T t)
 50         {
 51             DbContext.Set<T>().Attach(t);
 52             DbContext.Entry(t).State = EntityState.Modified;
 53             return SaveChanges() > 0;
 54         }
 55 
 56         public T SelectById(int id)
 57         {
 58             return DbContext.Set<T>().FirstOrDefault(s => s.Id == id);
 59         }
 60 
 61         public IEnumerable<T> SelectAll()
 62         {
 63             return DbContext.Set<T>();
 64         }
 65 
 66         public IPagedList<T> SelectPageList(int? pageIndex, int? pageSize)
 67         {
 68             IEnumerable<T> list = DbContext.Set<T>().OrderByDescending(s=>s.CreateTime);
 69             return list.ToPagedList(pageIndex??1,pageSize??10);
 70         }
 71 
 72         /// <summary>
 73         /// 提交数据库操作进行异常捕捉
 74         /// </summary>
 75         /// <returns></returns>
 76         private int SaveChanges()
 77         {
 78             try
 79             {
 80                 int result = DbContext.SaveChanges();
 81                 return result;
 82             }
 83             catch (System.Data.Entity.Infrastructure.DbUpdateException ex)
 84             {
 85                 string message = "error:";
 86                 if (ex.InnerException == null)
 87                     message += ex.Message + ",";
 88                 else if (ex.InnerException.InnerException == null)
 89                     message += ex.InnerException.Message + ",";
 90                 else if (ex.InnerException.InnerException.InnerException == null)
 91                     message += ex.InnerException.InnerException.Message + ",";
 92                 throw new Exception(message);
 93             }
 94         }
 95 
 96         public void Dispose()
 97         {
 98             DbContext.Dispose();
 99         }
100     }
101 }
DaoBase

数据库访问上下文

MyFrame.DataMapping.DataBaseContext

 1 using System.Data.Entity;
 2 using MyFrame.DataMapping.Mapping;
 3 using MyFrame.Domain;
 4 
 5 namespace MyFrame.DataMapping
 6 {
 7     /// <summary>
 8     /// 数据库访问上下文
 9     /// </summary>
10     public class DataBaseContext : DbContext
11     {
12         public DataBaseContext()
13             : base("Name=EhiBus")
14         {
15             Database.SetInitializer<DataBaseContext>(null);
16         }
17         //实体类
18         public DbSet<User> Users { get; set; }
19         public DbSet<Driver> Drivers { get; set; }
20         //将实体映射到数据库表
21         protected override void OnModelCreating(DbModelBuilder modelBuilder)
22         {
23             modelBuilder.Configurations.Add(new UserMap());
24             modelBuilder.Configurations.Add(new DriverMap());
25         }
26         
27     }
28 }
DataBaseContext
 1 using System.Data.Entity.ModelConfiguration;
 2 using MyFrame.Domain;
 3 
 4 namespace MyFrame.DataMapping.Mapping
 5 {
 6     public class UserMap : EntityTypeConfiguration<User>
 7     {
 8         public UserMap()
 9         {
10             this.HasKey(t => t.Id);
11             this.ToTable("User");
12             this.Property(t => t.Id).HasColumnName("Id");
13             this.Property(t => t.CreateTime).HasColumnName("CreateTime");
14         }
15     }
16 }
UserMap

扩展帮助类

MyFrame.Common.Helper:封装了一些常用的方法,我自己用起来比较顺手,增加自己的开发效率

  1 using System;
  2 
  3 namespace MyFrame.Common
  4 {
  5     public static class Helper
  6     {
  7         #region 字符串转换为Int
  8         /// <summary>
  9         /// 将字符串转换为Int?类型
 10         /// </summary>
 11         public static int? ToInt32(this string s)
 12         {
 13             int? num;
 14             try
 15             {
 16                 num = Convert.ToInt32(s);
 17             }
 18             catch (FormatException formatException)
 19             {
 20                 num = null;
 21             }
 22             catch (OverflowException overflowException)
 23             {
 24                 num = null;
 25             }
 26             return num;
 27         }
 28         
 29         /// <summary>
 30         /// 将字符串转换为Int类型
 31         /// </summary>
 32         public static int ToInt32Req(this string s)
 33         {
 34             try
 35             {
 36                 int num = Convert.ToInt32(s);
 37                 return num;
 38             }
 39             catch (FormatException ex)
 40             {
 41                 throw new Exception(ex.Message);
 42             }
 43             catch (OverflowException overflowException)
 44             {
 45                 throw new Exception(overflowException.Message);
 46             }
 47         }
 48         #endregion
 49 
 50         #region 字符串转换为Decimal
 51         /// <summary>
 52         /// 将字符串转换为Decimal?类型
 53         /// </summary>
 54         public static decimal? ToDecimal(this string s)
 55         {
 56             decimal? num;
 57             try
 58             {
 59                 num = Convert.ToDecimal(s);
 60             }
 61             catch (Exception formatException)
 62             {
 63                 num = null;
 64             }
 65             return num;
 66         }
 67 
 68         /// <summary>
 69         /// 将字符串转换为Decimal类型,无法转换抛出异常
 70         /// </summary>
 71         public static decimal ToDecimalReq(this string s)
 72         {
 73             try
 74             {
 75                 decimal num = Convert.ToDecimal(s);
 76                 return num;
 77             }
 78             catch (FormatException ex)
 79             {
 80                 throw new Exception(ex.Message);
 81             }
 82             catch (OverflowException overflowException)
 83             {
 84                 throw new Exception(overflowException.Message);
 85             }
 86         }
 87         #endregion
 88 
 89         #region 字符串转换为DateTime
 90         /// <summary>
 91         /// 将字符串转换为DateTime?类型
 92         /// </summary>
 93         public static DateTime? ToDateTime(this string s)
 94         {
 95             DateTime? num;
 96             try
 97             {
 98                 num = Convert.ToDateTime(s);
 99             }
100             catch (FormatException formatException)
101             {
102                 num = null;
103             }
104             return num;
105         }
106 
107         /// <summary>
108         /// 将字符串转换为DateTime类型,无法转换抛出异常
109         /// </summary>
110         public static DateTime ToDateTimeReq(this string s)
111         {
112             try
113             {
114                 DateTime num = Convert.ToDateTime(s);
115                 return num;
116             }
117             catch (FormatException ex)
118             {
119                 throw new Exception(ex.Message);
120             }
121         }
122         #endregion
123 
124         #region 字符串转换为bool
125         /// <summary>
126         /// 将字符串转换为bool?类型
127         /// </summary>
128         public static bool? ToBool(this string s)
129         {
130             bool? num;
131             try
132             {
133                 num = Convert.ToBoolean(s);
134             }
135             catch (FormatException formatException)
136             {
137                 num = null;
138             }
139             return num;
140         }
141 
142         /// <summary>
143         /// 将字符串转换为bool类型,无法转换抛出异常
144         /// </summary>
145         public static bool ToBoolReq(this string s)
146         {
147             try
148             {
149                 bool num = Convert.ToBoolean(s);
150                 return num;
151             }
152             catch (FormatException ex)
153             {
154                 throw new Exception(ex.Message);
155             }
156         }
157         #endregion
158 
159         #region 根据Text转换为Enum
160         /// <summary>
161         /// 根据Text转换为Enum?类型
162         /// </summary>
163         public static T? ToEnumByText<T>(this string s) where T:struct 
164         {
165             T? t;
166             try
167             {
168                 t = (T) Enum.Parse(typeof (T), s);
169             }
170             catch (Exception ex)
171             {
172                 t = null;
173             }
174             return t;
175         }
176 
177         /// <summary>
178         ///根据Text转换为Enum类型,无法转换抛出异常
179         /// </summary>
180         public static T ToEnumReqByText<T>(this string s) where T : struct 
181         {
182 
183             try
184             {
185                 T t= (T)Enum.Parse(typeof (T), s);
186                 return t;
187             }
188             catch (ArgumentNullException argumentNullException)
189             {
190                 throw new Exception(argumentNullException.Message);
191             }
192             catch (ArgumentException argumentException)
193             {
194                 throw new Exception(argumentException.Message);
195             }
196             catch (OverflowException overflowException)
197             {
198                 throw new Exception(overflowException.Message);
199             }
200         }
201         #endregion
202 
203         #region 根据Value转换为Enum
204         /// <summary>
205         /// 根据Value转换为Enum?类型
206         /// </summary>
207         public static T? ToEnumByValue<T>(this int s) where T : struct
208         {
209             T? t;
210             try
211             {
212                 t = (T)Enum.Parse(typeof(T), s.ToString());
213             }
214             catch (Exception ex)
215             {
216                 t = null;
217             }
218             return t;
219         }
220 
221         /// <summary>
222         ///根据Value转换为Enum类型,无法转换抛出异常
223         /// </summary>
224         public static T ToEnumByValueReq<T>(this int s) where T : struct
225         {
226 
227             try
228             {
229                 T t = (T)Enum.Parse(typeof(T), s.ToString());
230                 return t;
231             }
232             catch (ArgumentNullException argumentNullException)
233             {
234                 throw new Exception(argumentNullException.Message);
235             }
236             catch (ArgumentException argumentException)
237             {
238                 throw new Exception(argumentException.Message);
239             }
240             catch (OverflowException overflowException)
241             {
242                 throw new Exception(overflowException.Message);
243             }
244         }
245         #endregion
246 
247         
248     }
249 }
Helper

分页控件

我用得是PagedList,Nuget里搜索安装PagedList.MVC即可,然后自己封装了一下,封装得在DaoBase里SelectPageList()

为了让这个控件扩展性更强,写了一个分部试图_PageList,定义了一个分页Model,

为什么要自己写个而不是用它自己封装好的,因为后期页码可能需要跳转“首页”,”末页“等

 1 using PagedList;
 2 
 3 namespace MyFrame.Web.Models
 4 {
 5     public class PageListModel<T> where T:class 
 6     {
 7         public IPagedList<T> PageList { get; set; }
 8 
 9         public string Action { get; set; }
10 
11         public string Controller { get; set; }
12     }
13 }
PageListModel
 1 <div class="page-box">
 2     @if (Model.PageList.HasPreviousPage)
 3     {
 4         <a href="@Url.Action(Model.Action, Model.Controller, new { pageIndex = (Model.PageList.PageNumber - 1) })">上一页</a>
 5     }
 6     @for (int i = 1; i <= Model.PageList.PageCount; i++)
 7     {
 8         <a class="@(i == Model.PageList.PageNumber ? "currentpage" : "")" href="@Url.Action(Model.Action, Model.Controller, new { pageIndex = i })">@i</a>
 9     }
10     @if (Model.PageList.HasNextPage)
11     {
12         <a href="@Url.Action(Model.Action, Model.Controller, new { pageIndex = (Model.PageList.PageNumber + 1) })">下一页</a>
13     }
14 </div>
_PageList

分页css

1 /*分页*/
2 .page-box{ width:770px; height:40px; background:#FFF; padding-top:15px; text-align:right; padding-right:20px;}
3 .page-box a{text-decoration: none; padding:3px 7px; display:inline-block; text-align:center; border:1px solid #CFCFCF; color:#666; font-size:12px;}
4 .page-box a:hover{ background:#A4A4A4; color:#fff;}
5 .page-box .currentpage{ background:#CCC;}
PageList

怎么调用呢?跟调用分部试图方法一样,只是需要传进一个PageListModel

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 using MyFrame.Common;
 7 using MyFrame.Domain;
 8 using MyFrame.Dao;
 9 using MyFrame.IDao;
10 using PagedList;
11 
12 namespace MyFrame.Web.Controllers
13 {
14     public class HomeController : Controller
15     {
16         private readonly IUserDao _userDao;
17         private readonly IDriverDao _driverDao;
18         public HomeController(IUserDao userDao,IDriverDao driverDao)
19         {
20             _userDao = userDao;
21             _driverDao = driverDao;
22         }
23 
24         public ActionResult Index(int? pageIndex=1)
25         {
26             IPagedList<Driver> drivers = _driverDao.SelectPageList(pageIndex,2);
27             return View(drivers);
28         }
29 
30     }
31 }
Controller
 1 @using MyFrame.Domain
 2 @using MyFrame.Web.Models
 3 @model PagedList.IPagedList<MyFrame.Domain.Driver>
 4 @{
 5     ViewBag.Title = "Index";
 6     Layout = "~/Views/Shared/_Layout.cshtml";
 7 }
 8 
 9 @foreach (var driver in Model)
10 {
11     <p>@driver.Id</p>
12     <p>@driver.DriverName</p>
13     <p>@driver.Phone</p>
14 
15 }
16 
17 @Html.Partial("_PageList", new PageListModel<Driver> { PageList = Model, Action = "Index", Controller = "Home" })
Index

Autofac组件

控制反转,类似于Ioc容器的组件,通过配置接口对应具体的实现类

然后调用我们只需要调接口就行了,降低耦合性。

组件Nuget里有自己下载安装就行

在Globl.asax里配置

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Reflection;
 5 using System.Web;
 6 using System.Web.Http;
 7 using System.Web.Mvc;
 8 using System.Web.Optimization;
 9 using System.Web.Routing;
10 using Autofac;
11 using Autofac.Integration.Mvc;
12 using MyFrame.Common;
13 using MyFrame.Dao;
14 using MyFrame.IDao;
15 using MyFrame.IService;
16 using MyFrame.Service;
17 
18 namespace MyFrame.Web
19 {
20     // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
21     // 请访问 http://go.microsoft.com/?LinkId=9394801
22 
23     public class MvcApplication : System.Web.HttpApplication
24     {
25 
26         private void SetupResolveRules(ContainerBuilder builder)
27         {
28             //Components are wired to services using the As() methods on ContainerBuilder
29             builder.RegisterType<UserDao>().As<IUserDao>();
30             builder.RegisterType<UserService>().As<IUserService>();
31             builder.RegisterType<DriverDao>().As<IDriverDao>();
32         }
33         protected void Application_Start()
34         {
35             AreaRegistration.RegisterAllAreas();
36 
37             // 依赖注入
38             var builder = new ContainerBuilder();
39             SetupResolveRules(builder);
40             builder.RegisterControllers(Assembly.GetExecutingAssembly());
41             var container = builder.Build();
42             DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
43 
44             WebApiConfig.Register(GlobalConfiguration.Configuration);
45             FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
46             RouteConfig.RegisterRoutes(RouteTable.Routes);
47             BundleConfig.RegisterBundles(BundleTable.Bundles);
48         }
49     }
50 }
View Code

通过控制器里的构造方法,调用即可

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 using MyFrame.Common;
 7 using MyFrame.Domain;
 8 using MyFrame.Dao;
 9 using MyFrame.IDao;
10 using PagedList;
11 
12 namespace MyFrame.Web.Controllers
13 {
14     public class HomeController : Controller
15     {
16         private readonly IUserDao _userDao;
17         private readonly IDriverDao _driverDao;
18         public HomeController(IUserDao userDao,IDriverDao driverDao)
19         {
20             _userDao = userDao;
21             _driverDao = driverDao;
22         }
23 
24         public ActionResult Index(int? pageIndex=1)
25         {
26             IPagedList<Driver> drivers = _driverDao.SelectPageList(pageIndex,2);
27             return View(drivers);
28         }
29 
30     }
31 }
View Code

其实配置接口对应哪个具体实体的关系,应该放到config文件比较好,这个后期再慢慢优化把。

结尾

这是一个初级版本,后期肯定要再好好完善,比如加入Transaction事务管理,排序,条件查询等等。

大家如果有什么好的建议,尽管提,互相促进互相学习。

转载请注明出处,谢谢!

源代码下载地址http://yun.baidu.com/share/link?shareid=2761504180&uk=2820969304

 

posted @ 2015-06-08 10:48  孤独的十字  阅读(9386)  评论(51编辑  收藏  举报