- 现阶段使用回溯
entityframework作为.net平台自己的一个orm的框架,之前在项目中也有使用,主要采用了table和model first的方式,此两种感觉使用上也是大同小异。在项目中经常反应的一个问题源于多个开发团队共享一个数据库(3个开发团队使用同一个数据库,开发的是一个平台的各个业务场景),因而如在开发库(且记为19)A Team的 Lee 同学,修改了某表的字段,开发过程中 B Team某业务的项目使用EF架构,开发同学 Yang 在开发库上更新了整个table到model的映射,之后继续使用linq方式进行业务处理,一切没有问题,之后开发结束,提交代码构建到beta环境提交测试(测试环境并未A B Team共享,此为B Team的测试环境)此时因为A Team的 Lee 同学的脚本实际上是没有在beta数据库执行的,而程序已经更新过了,这样子就产生程序出错。实际上这理应属于管理问题,具体是sql脚本的管理规范,所以针对多团队的协作使用同一DB的情况下需要约定要么一个人负责DB的权限,或者共享一个sql script的脚本目录,任何数据库脚本,需即时更新进去,在构建或者发布动作保证同时对sql script进行execute(目前在trunk建立了sql script的共享目录以供此操作)。
2. 使用table first的方式创建演示项目
1) 创建演示数据库 EFTableModel,并创建演示对象。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 use EFTableModel 2 go 3 create table Users( 4 id int primary key, 5 username nvarchar(40) 6 ) 7 go 8 IF EXISTS (SELECT * FROM sysobjects WHERE name = 'Users_view') 9 DROP VIEW Users_view 10 GO 11 CREATE VIEW Users_view 12 AS 13 SELECT * FROM Users 14 GO 15 SELECT * FROM Users_view 16 go 17 create proc proc_users 18 as 19 select * from Users_view 20 go 21 exec proc_users
2) 创建演示项目,并建立table first 的基本映射模型
新建web项目,使用framework4.5
选择mvc,并设置 无身份验证
新建 ado.net 实体数据模型
选择从table生成,即为table first模式
设置连接数据库
选择映射模型的包含对象
如下,即为现下 table first 映射出的 model
3. 添加 mvc5 controller,进行数据库操作。
默认controller已经生成如下的示例代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Data; 4 using System.Data.Entity; 5 using System.Linq; 6 using System.Net; 7 using System.Web; 8 using System.Web.Mvc; 9 using EFTableModelApplication.Models; 10 11 namespace EFTableModelApplication.Controllers 12 { 13 public class UserController : Controller 14 { 15 private EFTableModelEntities db = new EFTableModelEntities(); 16 17 // GET: /User/ 18 public ActionResult Index() 19 { 20 return View(db.Users.ToList()); 21 } 22 23 // GET: /User/Details/5 24 public ActionResult Details(int? id) 25 { 26 if (id == null) 27 { 28 return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 29 } 30 Users users = db.Users.Find(id); 31 if (users == null) 32 { 33 return HttpNotFound(); 34 } 35 return View(users); 36 } 37 38 // GET: /User/Create 39 public ActionResult Create() 40 { 41 return View(); 42 } 43 44 // POST: /User/Create 45 // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 46 // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。 47 [HttpPost] 48 [ValidateAntiForgeryToken] 49 public ActionResult Create([Bind(Include="id,username")] Users users) 50 { 51 if (ModelState.IsValid) 52 { 53 db.Users.Add(users); 54 db.SaveChanges(); 55 return RedirectToAction("Index"); 56 } 57 58 return View(users); 59 } 60 61 // GET: /User/Edit/5 62 public ActionResult Edit(int? id) 63 { 64 if (id == null) 65 { 66 return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 67 } 68 Users users = db.Users.Find(id); 69 if (users == null) 70 { 71 return HttpNotFound(); 72 } 73 return View(users); 74 } 75 76 // POST: /User/Edit/5 77 // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 78 // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。 79 [HttpPost] 80 [ValidateAntiForgeryToken] 81 public ActionResult Edit([Bind(Include="id,username")] Users users) 82 { 83 if (ModelState.IsValid) 84 { 85 db.Entry(users).State = EntityState.Modified; 86 db.SaveChanges(); 87 return RedirectToAction("Index"); 88 } 89 return View(users); 90 } 91 92 // GET: /User/Delete/5 93 public ActionResult Delete(int? id) 94 { 95 if (id == null) 96 { 97 return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 98 } 99 Users users = db.Users.Find(id); 100 if (users == null) 101 { 102 return HttpNotFound(); 103 } 104 return View(users); 105 } 106 107 // POST: /User/Delete/5 108 [HttpPost, ActionName("Delete")] 109 [ValidateAntiForgeryToken] 110 public ActionResult DeleteConfirmed(int id) 111 { 112 Users users = db.Users.Find(id); 113 db.Users.Remove(users); 114 db.SaveChanges(); 115 return RedirectToAction("Index"); 116 } 117 118 protected override void Dispose(bool disposing) 119 { 120 if (disposing) 121 { 122 db.Dispose(); 123 } 124 base.Dispose(disposing); 125 } 126 } 127 }
可以看到,至此没有手工书写任何代码层面的东西,完全自动集成,就可以使用EFTableModelEntities对象实例直接操作各个数据表。
最后访问,http://localhost:63790/user,已经内置了基本crud操作。
3. 使用 table first 方式 从数据库 更新 model
首先执行以下脚本,即增加User表一个salary字段:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 use EFTableModel 2 alter table Users add salary money 3 go
在设计界面,右键,选择 从数据库更新模型,进行数据模型的更新。
更新结束之后,结果如下图所示:
修改index视图:
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 @model IEnumerable<EFTableModelApplication.Models.Users> 2 3 @{ 4 ViewBag.Title = "Index"; 5 } 6 7 <h2>Index</h2> 8 9 <p> 10 @Html.ActionLink("Create New", "Create") 11 </p> 12 <table class="table"> 13 <tr> 14 <th> 15 @Html.DisplayNameFor(model => model.username) 16 </th> 17 <th> 18 @Html.DisplayNameFor(model => model.salary) 19 </th> 20 <th></th> 21 </tr> 22 23 @foreach (var item in Model) { 24 <tr> 25 <td> 26 @Html.DisplayFor(modelItem => item.username) 27 </td> 28 <td> 29 @Html.DisplayFor(modelItem => item.salary) 30 </td> 31 <td> 32 @Html.ActionLink("Edit", "Edit", new { id=item.id }) | 33 @Html.ActionLink("Details", "Details", new { id=item.id }) | 34 @Html.ActionLink("Delete", "Delete", new { id=item.id }) 35 </td> 36 </tr> 37 } 38 39 </table>
再次查看列表页面,显示正常:
4. ef架构模型及C-S mapping(ConceptualModels-StorageModels)
StorageModels:可以理解为仓库模型或者就是持久化的模型(物理模型)定义,在对定义了数据库存储的结构如:
ConceptualModels:可以理解为概念上的,类对象层面的模型结构,如:
而,物理模型和概念模型,之间形成O-R mapping的对应关系:
我们在数据库中修改某些字段类型之后,完全可以据此直接使用文本文件打开对应的 *.edmx 修改该xml文件对应字段的字段类型,之后在vs中会自动提示重新加载,就可以达到修改字段的目的。同样,掌握这个结构可以直接针对添加数据库表字段的情况,进而编辑该xml文件,添加对应的节点,达成效果。
5.code-first的方式以及启动数据迁移 //todo
6.生产环境情况的更新模式 //todo