MVC5 + EF6 入门完整教程 四

来源:互联网 发布:网络恐怖主义的成因 编辑:程序博客网 时间:2024/05/22 03:05

跟着这个教程学习,已经将自己写的代码上传到git上,有需要的可以下载,如有问题欢迎留言,后续会持续更新https://github.com/bloodymandoo/mvc5

上篇文章主要讲了如何配置EF, 我们回顾下主要过程:

创建Data Model à 创建Database Context à创建databaseInitializerà配置entityFramework的context配置节。

对这个过程还有疑问的可以去上篇再看一下。

本次我们就主要讲解 (1) EF基本的CRUD (2) 涉及到的常用HtmlHelper


文章提纲


概述 & 要点

理论基础

详细步骤

总结


概述 & 要点


下面是本文要点,正文部分会有详细介绍。

  • EF数据模型的CRUD
  • 常用的HtmlHelper
  • Repository Pattern


理论基础 -- EF 三种编程方式 (略)


总共有三种方式:

Database First,Model First和Code First,我们采用的是code first.

这方面资料很多,我就不重复讲述了, 需要了解这三者差异和应用场景的请自行查阅其他资料。


理论基础 -- EF CRUD


针对之前创建的SysUser, SysRole, SysUserRole举一些典型例子,基本的CRUD大家在使用时模仿这些例子就可以了。

我们要用的数据库示例数据分别如下:    

SysUser

SysRole

SysUserRole

EF数据查询

先讲使用频率最高的查询部分。     

EF数据查询用LINQ实现(LINQ to Entities),通常有表达式和函数式两种方式。建议用函数式方式,比较简单。

假设我们已经定义好了context

privateAccountContext db =newAccountContext();

  1. [基本查询] 查询所有的SysUser

    

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. var users =from uin db.SysUsers  
  2.   
  3. ct u;//表达式方式  
  4.   
  5. users = db.SysUsers;//函数式方式  

  1. [条件查询] 加入查询条件

  

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1.   users =from uin db.SysUsers  
  2.   
  3. where u.UserName =="Tom"  
  4.   
  5. select u;//表达式方式  
  6.   
  7. users = db.SysUsers.Where(u => u.UserName =="Tom");//函数式方式  

    NOTE 注意这边等号是C#写法 :" =="

  1. [排序和分页查询]

    

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1.     users = (from uin db.SysUsers  
  2.   
  3. orderby u.UserName  
  4.   
  5. select u).Skip(0).Take(5);//表达式方式  
  6.   
  7. users = db.SysUsers.OrderBy(u => u.UserName).Skip(0).Take(5);//函数式方式  

    NOTE 只有排序了才能分页

  1. [聚合查询]

    

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1.     //查user总数  
  2.   
  3. var num = db.SysUsers.Count();  
  4.   
  5. //查最小ID  
  6.   
  7. var minId = db.SysUsers.Min(u => u.ID);  

    NOTE 聚合查询只能通过函数式查询

  1. [连接查询]

   

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. var users =from urin db. SysUserRoles  
  2.   
  3.  join uin db. SysUsers  
  4.   
  5.  on ur.SysUserIDequals u.ID  
  6.   
  7. elect ur;  

NOTE

大家注意,连接查询返回的结果还是一个类型为SysUserRoles的集合,只是用了内连接进行了的筛选。

那么问题来了,如果我需要选择一个集合,里面包括多张表,如SysUser里面的UserName和SysRole里面的RoleName怎么办?

这个是通过navigation property来实现的, 前面新建model的时候提到过,例如SysUser里面的

publicvirtualICollection<SysUserRole> SysUserRoles {get;set; }

但这种做法还是不是太灵活,具体做法我们在下面的详细步骤里面讲。

EF数据更新

UPDATE步骤比较清晰,直接看下面代码。


[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. //数据更新,分三步:找到对象--> 更新对象数据--> 保存更改  
  2.   
  3.   public ActionResult EFUpdateDemo()  
  4.   
  5.   {  
  6.   
  7.      //1.找到对象  
  8.       var sysUser = db.SysUsers.FirstOrDefault(u => u.UserName =="Tom");  
  9.     //2.更新对象数据  
  10.   
  11.       if (sysUser !=null)  
  12.   
  13.        {  
  14.   
  15.          sysUser.UserName ="Tom2";  
  16.   
  17.        }  
  18.   
  19.    //3.保存修改  
  20.   
  21.    db.SaveChanges();  
  22.   
  23.    return View();  
  24.   
  25. }  


EF数据添加/删除

与UPDATE类似。

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. //数据添加和删除  
  2.   
  3. publicActionResult EFAddOrDeleteDemo()  
  4.   
  5. {  
  6.   
  7. //添加  
  8.   
  9. //1.创建新的实体  
  10.   
  11. var newSysUser =newSysUser()  
  12.   
  13. {  
  14.   
  15. UserName ="Scott",  
  16.   
  17. Password ="tiger",  
  18.   
  19. Email ="Scott@sohu.com"  
  20.   
  21. };  
  22.   
  23. //2.增加  
  24.   
  25. db.SysUsers.Add(newSysUser);  
  26.   
  27. //3.保存修改  
  28.   
  29. db.SaveChanges();  
  30.   
  31.    
  32.   
  33. //删除  
  34.   
  35. //1.找到需要删除的对象  
  36.   
  37. var delSysUser = db.SysUsers.FirstOrDefault(u => u.UserName =="Scott");  
  38.   
  39. //2.删除  
  40.   
  41. if (delSysUser!=null)  
  42.   
  43. {  
  44.   
  45. db.SysUsers.Remove(delSysUser);  
  46.   
  47. }  
  48.   
  49. //3.保存修改  
  50.   
  51. db.SaveChanges();  
  52.   
  53. return View("EFQueryDemo");  
  54.   
  55. }  



详细步骤


  • 查询用户及相应角色的功能
  • 修改用户
  • 增加用户和删除用户

查询用户及相应的角色

  1. 在Controller中修改Index方法,添加相关View, 显示所有用户
    1. 将model作为参数传过去

    2. Viewsà Accountà Index.cshtml 顶部添加强类型声明,

      @modelIEnumerable<MVCDemo.Models.SysUser>

      body中添加个table用来显示数据

      NOTE

      @Html.ActionLink("Details","Details",new { id = item.ID })生成一个相同controller下的路由地址。

      显示结果

       

  2. 增加一个Details方法,添加相关View, 显示相应用户及对应的角色
    1. 将特定的model传过去

       

    2. Viewsà Accountà Index.cshtml 顶部添加强类型声明

      @modelMVCDemo.Models.SysUser

      显示数据,注意方框部分如何导航到另外一张表的信息中。

      显示结果

       

更新用户,增加用户,删除用户

这三个操作都类似,属于更新的范畴,我们放在一起来讲。

  1. 修改Viewsà Accountà Index.cshtml

    开头增加Create链接。

    table每条记录后面增加Edit,Delete链接。

     

  2. 在Controller中增加相应的方法。

    新建用户:

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. //新建用户  
  2.   
  3. public ActionResult Create()  
  4.   
  5. {  
  6.   
  7. return View();  
  8.   
  9. }  
  10.   
  11. [HttpPost]  
  12.   
  13. public ActionResult Create(SysUser sysUser)  
  14.   
  15. {  
  16.   
  17. db.SysUsers.Add(sysUser);  
  18.   
  19. db.SaveChanges();  
  20.   
  21. return RedirectToAction("Index");  
  22.   
  23. }  


修改用户:

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. //修改用户  
  2.   
  3. public ActionResult Edit(int id)  
  4.   
  5. {  
  6.   
  7. SysUser sysUser = db.SysUsers.Find(id);  
  8.   
  9. return View(sysUser);  
  10.   
  11. }  
  12.   
  13. [HttpPost]  
  14.   
  15. public ActionResult Edit(SysUser sysUser)  
  16.   
  17. {  
  18.   
  19. db.Entry(sysUser).State =EntityState.Modified;  
  20.   
  21. db.SaveChanges();  
  22.   
  23. return RedirectToAction("Index");  
  24.   
  25. }  


删除用户:

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. //删除用户  
  2.   
  3. public ActionResult Delete(int id)  
  4.   
  5. {  
  6.   
  7. SysUser sysUser = db.SysUsers.Find(id);  
  8.   
  9. return View(sysUser);  
  10.   
  11. }  
  12.   
  13. [HttpPost,ActionName("Delete")]  
  14.   
  15. public ActionResult DeleteConfirmed(int id)  
  16.   
  17. {  
  18.   
  19. SysUser sysUser = db.SysUsers.Find(id);  
  20.   
  21. db.SysUsers.Remove(sysUser);  
  22.   
  23. db.SaveChanges();  
  24.   
  25. return RedirectToAction("Index");  
  26.   
  27. }  


NOTE

涉及到数据更新的地方都有两个同名的方法重载,一个用来显示[HttpGet],一个用来数据更新[HttpPost]

  1. 在右键方法名,生成相应的View

    每个View的顶部需要添加一个声明

    @modelMVCDemo.Models.SysUser

    各个view的body中具体代码:

    Create.cshtm

[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. <body>  
  2.     <div>  
  3.         <h2>Create</h2>  
  4.         @using (Html.BeginForm())  
  5.         {  
  6.             <div>  
  7.                 @Html.LabelFor(model => model.UserName)  
  8.                 @Html.EditorFor(model => model.UserName)  
  9.             </div>  
  10.             <div>  
  11.                 @Html.LabelFor(model => model.Email)  
  12.                 @Html.EditorFor(model => model.Email)  
  13.             </div>  
  14.             <div>  
  15.                 @Html.LabelFor(model => model.Password)  
  16.                 @Html.PasswordFor(model => model.Password)  
  17.             </div>  
  18.             <div>  
  19.                 <inputtypeinputtype ="submit" value="Create" />  
  20.             </div>  
  21.         }  
  22.         <div>@Html.ActionLink("Back to List", "Index")</div>  
  23.     </div>  
  24. </body>  



Edit.cshtml

[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. <body>  
  2.   
  3.     <div>  
  4.   
  5.         <h2>Edit</h2>  
  6.   
  7.         @using (Html.BeginForm())  
  8.         {  
  9.   
  10.             @Html.HiddenFor(model => model.ID)  
  11.   
  12.             <div>  
  13.   
  14.                 @Html.LabelFor(model => model.UserName)  
  15.   
  16.                 @Html.EditorFor(model => model.UserName)  
  17.   
  18.             </div>  
  19.   
  20.             <div>  
  21.   
  22.                 @Html.LabelFor(model => model.Email)  
  23.   
  24.                 @Html.EditorFor(model => model.Email)  
  25.   
  26.             </div>  
  27.   
  28.             <div>  
  29.   
  30.                 @Html.LabelFor(model => model.Password)  
  31.   
  32.                 @Html.PasswordFor(model => model.Password)  
  33.   
  34.             </div>  
  35.   
  36.             <div>  
  37.   
  38.                 <inputtypeinputtype ="submit" value="Save" />  
  39.   
  40.             </div>  
  41.   
  42.         }  
  43.   
  44.         <div>@Html.ActionLink("Back to List", "Index")</div>  
  45.   
  46.     </div>  
  47.   
  48. </body>  


Delete.cshtml

[html] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. <body>  
  2.   
  3.     <div>  
  4.   
  5.         <h2>Delete</h2>  
  6.   
  7.         <h3>Are you sure you want to delete this?</h3>  
  8.   
  9.         <h4>User</h4>  
  10.   
  11.         <dl>  
  12.   
  13.             <dt>@Html.DisplayNameFor(model => model.UserName)</dt>  
  14.   
  15.             <dd>@Html.DisplayFor(model => model.UserName)</dd>  
  16.   
  17.   
  18.   
  19.             <dt>@Html.DisplayNameFor(model => model.Email)</dt>  
  20.   
  21.             <dd>@Html.DisplayFor(model => model.Email)</dd>  
  22.   
  23.         </dl>  
  24.   
  25.   
  26.   
  27.         @using (Html.BeginForm())  
  28.         {  
  29.   
  30.             <div>  
  31.   
  32.                 <inputtypeinputtype ="submit" value="Delete" />  
  33.   
  34.             </div>  
  35.   
  36.         }  
  37.   
  38.         <div>  
  39.   
  40.             @Html.ActionLink("Back to List", "Index")  
  41.   
  42.         </div>  
  43.   
  44.     </div>  
  45.   
  46. </body>  


NOTE

针对上面这些代码,我们提一下其中用到的HtmlHelper, 主要有这么几个:

DisplayNameFor (model=>model.xxx)à 生成纯文本,显示xxx列名

DisplayFor (model=>model.xxx)à 生成纯文本,显示xxx列的内容

LableFor à 生成一个Lable标签

EditorFor à 生成一个text类型的input

PasswordFor à 类似于EditorFor, 隐藏文本内容

ActionLink à 生成一个<a>标签

BeginForm à 生成一个表单

NOTE

HtmlHelper是可以通过View的Html属性调用的方法(@Html.xxx), 可以类比成原来WebForm的服务器端控件, 后续文章会将分成几类, 归类进行介绍,这里先简单提一下做个铺垫。这块最好的学习方法是用浏览器打开相应的页面,View page source,查看生成的相应HTML代码。


Repository Pattern


最好再补充下Repository Pattern,为下篇文章重构代码做个铺垫。

Repository Pattern是一种设计模式,这个概念大家肯定经常听到。

"企业架构模式" 上的定义:

Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.

具体的做法:

先定义Interface, 通过定义接口确定数据访问类的功能需求, 接着实现该接口。

以对SysUser这张表的操作为例。

先建一个文件夹 Repositories, 在文件夹中新建一个接口IsysUserRepository

我们预先定义几个功能。

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. namespace MVCDemo.Repositories  
  2.   
  3. {  
  4.   
  5. public interfaceISysUserRepository  
  6.   
  7. {  
  8.   
  9. //查询所有用户  
  10.   
  11. IQueryable<SysUser> SelectAll();  
  12.   
  13. //通过用户名查询用户  
  14.   
  15. SysUser SelectByName(string userName);  
  16.   
  17. //添加用户  
  18.   
  19. void Add(SysUser sysUser);  
  20.   
  21. //删除用户  
  22.   
  23. bool Delete(int id);  
  24.   
  25. }  
  26. }  


同样文件夹下新建类,继承接口,实现功能。

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. namespace MVCDemo.Repositories  
  2.   
  3. {  
  4.   
  5. public classSysUserRepository : ISysUserRepository  
  6.   
  7. {  
  8.   
  9. protected AccountContext db =new AccountContext();  
  10.   
  11. //查询所有用户  
  12.   
  13. public IQueryable<SysUser> SelectAll()  
  14.   
  15. {  
  16.   
  17. return db.SysUsers;  
  18.   
  19. }  
  20.   
  21. //通过用户名查询用户  
  22.   
  23. public SysUser SelectByName(string userName)  
  24.   
  25. {  
  26.   
  27. return db.SysUsers.FirstOrDefault(u => u.UserName == userName);  
  28.   
  29. }  
  30.   
  31. //添加用户  
  32.   
  33. public void Add(SysUser sysUser)  
  34.   
  35. {  
  36.   
  37. db.SysUsers.Add(sysUser);  
  38.   
  39. db.SaveChanges();  
  40.   
  41. }  
  42.   
  43. //删除用户  
  44.   
  45. public bool Delete(int id)  
  46.   
  47. {  
  48.   
  49. var delSysUser=db.SysUsers.FirstOrDefault(u => u.ID == id);  
  50.   
  51. if (delSysUser !=null)  
  52.   
  53. {  
  54.   
  55. db.SysUsers.Remove(delSysUser);  
  56.   
  57. db.SaveChanges();  
  58.   
  59. returntrue;  
  60.   
  61. }  
  62.   
  63. else  
  64.   
  65. {  
  66.   
  67. returnfalse;  
  68.   
  69. }  
  70.   
  71. }  
  72.   
  73. }  
  74.   
  75. }  


通过IsysUserRepository接口对象引用SysUserRepository类的实例来调用:

[csharp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. ISysUserRepository ur=new SysUserRepository();  
  2.   
  3. var user=ur.xxx;   

怎么样,平时听到的Repository Pattern实现起来就这么简单。

楼主提示 设计模式都来源于编程实践,只要掌握其中几个重要原则,GOF总结的设计模式都能自己推导出来,就类似于几何中的公理和定理的关系。大家工作中做个有心人,多思考,多总结。

 


总结


OK,到此为止,我们对常用的CRUD做了介绍。View, Controller之间都是通过传递Model来交互的。特别要提下下面这张图,通过navigation property实现SysUserà SysUserRoleà SysRole 多表间查询。

当然,这种做法还是有局限性的,后续文章中我们会介绍如何实现类似于之前SQL查询多个表,将多个表的查询结果,例如datatable直接传到view中来显示数据。

好了,今天就到这里。


转载自 三天不学习 :http://blog.csdn.net/mss359681091/article/details/52135855

0 0
原创粉丝点击