MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具
MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具集成Visual Studio 2013
MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具
经过一个多星期的努力总算完成了单表,多表关联(一对多,多对一)的增删改查的代码生成,基本上可以实现不用添加任何代码完成对数据表的操作。
下个阶段打算集成.net 4.5的认证和授权已经用户注册和角色管理
一旦有更好的方式我会把它集成到模板中实现自动生成。所以很希望得到大家的帮助。在这里我先抛砖引玉了。
asp.net MVC 5 Scaffolding多层架构代码生成向导开源项目(邀请你的参与)
Demo和所有源代码代码在 https://github.com/neozhu/MVC5-Scaffolder
先看一下我的Demo实例

实体类的结构
Order 与 OrderDetail 一对多,OrderDetail 与 Product 多对一,Order与Product则是多对多的关系。
实现的操作界面如下图
查询界面

功能:
1/新增操作 : 页面跳转到新增页面
2/删除操作 : 选择记录或单击行上的删除 弹出确认框 是否删除改记录
3/编辑操作 : 单击行上的编辑图标页面跳转到编辑页面
4/查询操作 : 在Search 文本框中输入关键字会根据后台每个字段的查询,选择需要显示的字段

5/Table功能 :字段显示勾选,分页显示,所有功能都是服务端实现
新增页面


功能:
布局:上部表头,下部的Tab为表体明细
一对多 :表体用table显示
多对一 :用Dropdownlist进行选择
表体明细的操作 :使用popup modal的方式操作
单击保存后,系统会自动合并表头表体一起提交到后台进行保存
编辑页面

功能:
加载数据:会根据主从关系把表头/表体的数据一次性加载
编辑数据:对表体明细的的操作类似新增页面,但对表体进行删除操作时会进行提示是否真的要删除后台数据。
保存数据:一次性提交所有表头/表体数据到后台进行操作。
上述这些功能完全可以代码生成 不需要做任何修改
项目结构
View层的代码

Index :查询Table List
Create :新增页面
Edit : 编辑页面
EditForm :Partial View内嵌在Create 和Edit页面中
_OrderDetailForm : pupup 子表维护表单页面
Create,和Edit页面通过Ajax Post 把数据提交到后台的Controller进行操作
代码如下

<script type="text/javascript">
var orderid = 0;
var ObjectState = "Added";
var $orderdetailstable = {};
$(document).ready(function () {
$('form').submit(function () {
var token = $('[name=__RequestVerificationToken]').val();
var serializedForm = $(this).serialize();
var actionurl = $(this).attr('action');
var orderdetails = $orderdetailstable.bootstrapTable('getData');
var newitem = {
OrderDetails: orderdetails,
Id: orderid,
Customer: $('#Customer', 'form').val(),
ShippingAddress: $('#ShippingAddress', 'form').val(),
OrderDate: $('#OrderDate', 'form').val(),
ObjectState: ObjectState
};
$.ajax({
url: actionurl,
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(newitem),
success: function (result) {
if (result.success) {
self.location = "/Orders/Index";
} else {
alert(result.err);
}
},
error: function (result) {
console.log(result.statusText + result.responseText);
alert(result.statusText + result.responseText);
}
});
return false;
});
});
</script>

通过Jquery 获取表头和表体数据 序列化成Json对象然后Post到后台
Controller层代码
这里就只贴Create方法的代码

public class OrdersController : Controller
{
//private StoreContext db = new StoreContext();
private readonly IOrderService _orderService;
private readonly IUnitOfWorkAsync _unitOfWork; public OrdersController(IOrderService orderService, IUnitOfWorkAsync unitOfWork)
{
_orderService = orderService;
_unitOfWork = unitOfWork;
} // GET: Orders/Index
public ActionResult Index()
{ var orders = _orderService.Queryable().AsQueryable();
return View(orders);
} // Get :Orders/PageList
// For Index View Boostrap-Table load data
[HttpGet]
public ActionResult PageList(int offset = 0, int limit = 10, string search = "", string sort = "", string order = "")
{
int totalCount = 0;
int pagenum = offset / limit + 1;
var orders = _orderService.Query(new OrderQuery().WithAnySearch(search)).OrderBy(n => n.OrderBy(sort, order)).SelectPage(pagenum, limit, out totalCount);
var rows = orders.Select(n => new { Id = n.Id, Customer = n.Customer, ShippingAddress = n.ShippingAddress, OrderDate = n.OrderDate }).ToList();
var pagelist = new { total = totalCount, rows = rows };
return Json(pagelist, JsonRequestBehavior.AllowGet);
} // GET: Orders/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Order order = _orderService.Find(id);
if (order == null)
{
return HttpNotFound();
}
return View(order);
} // GET: Orders/Create
public ActionResult Create()
{
return View();
} // POST: Orders/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "OrderDetails,Id,Customer,ShippingAddress,OrderDate")] Order order)
{
if (ModelState.IsValid)
{
order.ObjectState = ObjectState.Added;
foreach (var item in order.OrderDetails)
{
item.OrderId = order.Id;
item.ObjectState = ObjectState.Added;
}
_orderService.InsertOrUpdateGraph(order);
_unitOfWork.SaveChanges();
if (Request.IsAjaxRequest())
{
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
DisplaySuccessMessage("Has append a Order record");
return RedirectToAction("Index");
} if (Request.IsAjaxRequest())
{
var modelStateErrors = String.Join("", this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors.Select(n => n.ErrorMessage)));
return Json(new { success = false, err = modelStateErrors }, JsonRequestBehavior.AllowGet);
}
DisplayErrorMessage();
return View(order);
} // GET: Orders/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Order order = _orderService.Find(id);
if (order == null)
{
return HttpNotFound();
}
return View(order);
} // POST: Orders/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "OrderDetails,Id,Customer,ShippingAddress,OrderDate")] Order order)
{
if (ModelState.IsValid)
{
order.ObjectState = ObjectState.Modified;
foreach (var item in order.OrderDetails)
{
item.OrderId = order.Id;
//set ObjectState with conditions
if (item.Id <= 0)
item.ObjectState = ObjectState.Added;
else
item.ObjectState = ObjectState.Modified;
} _orderService.InsertOrUpdateGraph(order); _unitOfWork.SaveChanges();
if (Request.IsAjaxRequest())
{
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
DisplaySuccessMessage("Has update a Order record");
return RedirectToAction("Index");
}
if (Request.IsAjaxRequest())
{
var modelStateErrors = String.Join("", this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors.Select(n => n.ErrorMessage)));
return Json(new { success = false, err = modelStateErrors }, JsonRequestBehavior.AllowGet);
}
DisplayErrorMessage();
return View(order);
} // GET: Orders/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Order order = _orderService.Find(id);
if (order == null)
{
return HttpNotFound();
}
return View(order);
} // POST: Orders/Delete/5
[HttpPost, ActionName("Delete")]
//[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Order order = _orderService.Find(id);
_orderService.Delete(order);
_unitOfWork.SaveChanges();
if (Request.IsAjaxRequest())
{
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
DisplaySuccessMessage("Has delete a Order record");
return RedirectToAction("Index");
} // Get Detail Row By Id For Edit
// Get : Orders/EditOrderDetail/:id
[HttpGet]
public ActionResult EditOrderDetail(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var orderdetailRepository = _unitOfWork.Repository<OrderDetail>();
var orderdetail = orderdetailRepository.Find(id); var orderRepository = _unitOfWork.Repository<Order>();
var productRepository = _unitOfWork.Repository<Product>(); if (orderdetail == null)
{
ViewBag.OrderId = new SelectList(orderRepository.Queryable(), "Id", "Customer");
ViewBag.ProductId = new SelectList(productRepository.Queryable(), "Id", "Name"); //return HttpNotFound();
return PartialView("_OrderDetailEditForm", new OrderDetail());
}
else
{
ViewBag.OrderId = new SelectList(orderRepository.Queryable(), "Id", "Customer", orderdetail.OrderId);
ViewBag.ProductId = new SelectList(productRepository.Queryable(), "Id", "Name", orderdetail.ProductId); }
return PartialView("_OrderDetailEditForm", orderdetail); } // Get Create Row By Id For Edit
// Get : Orders/CreateOrderDetail
[HttpGet]
public ActionResult CreateOrderDetail()
{
var orderRepository = _unitOfWork.Repository<Order>();
ViewBag.OrderId = new SelectList(orderRepository.Queryable(), "Id", "Customer");
var productRepository = _unitOfWork.Repository<Product>();
ViewBag.ProductId = new SelectList(productRepository.Queryable(), "Id", "Name");
return PartialView("_OrderDetailEditForm"); } // Post Delete Detail Row By Id
// Get : Orders/DeleteOrderDetail/:id
[HttpPost, ActionName("DeleteOrderDetail")]
public ActionResult DeleteOrderDetailConfirmed(int id)
{
var orderdetailRepository = _unitOfWork.Repository<OrderDetail>();
orderdetailRepository.Delete(id);
_unitOfWork.SaveChanges();
if (Request.IsAjaxRequest())
{
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
DisplaySuccessMessage("Has delete a Order record");
return RedirectToAction("Index");
} // Get : Orders/GetOrderDetailsByOrderId/:id
[HttpGet]
public ActionResult GetOrderDetailsByOrderId(int id)
{
var orderdetails = _orderService.GetOrderDetailsByOrderId(id);
if (Request.IsAjaxRequest())
{
return Json(orderdetails.Select(n => new { OrderCustomer = n.Order.Customer, ProductName = n.Product.Name, Id = n.Id, ProductId = n.ProductId, Qty = n.Qty, Price = n.Price, Amount = n.Amount, OrderId = n.OrderId }), JsonRequestBehavior.AllowGet);
}
return View(orderdetails); } private void DisplaySuccessMessage(string msgText)
{
TempData["SuccessMessage"] = msgText;
} private void DisplayErrorMessage()
{
TempData["ErrorMessage"] = "Save changes was unsuccessful.";
} protected override void Dispose(bool disposing)
{
if (disposing)
{
//_unitOfWork.Dispose();
}
base.Dispose(disposing);
}
}

Popup Modal编辑子表数据代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
<script type="text/javascript"> var currentrowindex = -1; function deleteOrderDetail(id) { var url = '@Url.Action("DeleteOrderDetail")'; bootbox.dialog({ message: "Are you sure delete " + id, title: "Delete OrderDetail ", buttons: { Cancel: { label: "Cancel", className: "btn-default", callback: function () { } }, OK: { label: "OK", className: "btn-success", callback: function () { $.post(url, { id: id }, function (data) { $orderdetailstable.bootstrapTable('remove', { field: 'Id', values: [id] }); //console.log('remove' + row.Id); }); } } } }); } function orderdetailsrowindexFormatter(value, row, index) { return index + 1; } function orderdetailsactionFormatter(value, row, index) { return [ '<a class="edit" id="orderdetailsedit" href="javascript:void(0)" title="Add">', '<i class="glyphicon glyphicon-edit"></i>', '</a> ', ' <a class="remove" id="orderdetailsremove" href="javascript:void(0)" title="Remove">', '<i class="glyphicon glyphicon-remove"></i>', '</a>' ].join(''); } window.actionEvents = { 'click #orderdetailsedit': function (e, value, row, index) { currentrowindex = index; var url = "/Orders/EditOrderDetail" $.get(url + '/' + row.Id, function (data) { $('#orderdetailformModal-body').html(data); if (row.Id > 0) { //var id = $('#Id','#orderdetailformModal-body'); //id.val(row.Id); //var productid = $('#ProductId','#orderdetailformModal-body'); //productid.val(row.ProductId); //var qty = $('#Qty','#orderdetailformModal-body'); //qty.val(row.Qty); //var price = $('#Price','#orderdetailformModal-body'); //price.val(row.Price); //var amount = $('#Amount','#orderdetailformModal-body'); //amount.val(row.Amount); //var orderid = $('#OrderId','#orderdetailformModal-body'); //orderid.val(row.OrderId); } else { var id = $('#Id', '#orderdetailformModal-body'); id.val(row.Id); var productid = $('#ProductId', '#orderdetailformModal-body'); productid.val(row.ProductId); var qty = $('#Qty', '#orderdetailformModal-body'); qty.val(row.Qty); var price = $('#Price', '#orderdetailformModal-body'); price.val(row.Price); var amount = $('#Amount', '#orderdetailformModal-body'); amount.val(row.Amount); var orderid = $('#OrderId', '#orderdetailformModal-body'); orderid.val(row.OrderId); } $('#orderdetailformModal').modal('toggle'); }); }, 'click #orderdetailsremove': function (e, value, row, index) { if (row.Id > 0) { deleteOrderDetail(row.Id); } else { $orderdetailstable.bootstrapTable('remove', { field: '$index', values: [index] }); } } }; $(function () { $orderdetailstable = $('#orderdetails-table').bootstrapTable({ data: [] }); if (ObjectState == "Modified") { orderid = $('#Id').val(); var url = '/Orders/GetOrderDetailsByOrderId/' + orderid; $.get(url, function (data) { //console.log(data); $orderdetailstable.bootstrapTable('load', data) }) } $('#addorderdetailsbutton').on('click', function (e) { if ($("form").valid()) { currentrowindex = -1; var url = "/Orders/CreateOrderDetail" $.get(url, function (data) { //console.log(data); var index = -1; $('#orderdetailformModal-body').html(data); $('#Id', '#orderdetailformModal-body').val(0); $('#OrderId', '#orderdetailformModal-body').val(orderid); $('#orderdetailformModal').modal('toggle'); }); } e.preventDefault(); //Return false regardless of validation to stop form submitting //prior to ajax doing its thing return false; }) $('#orderdetailconfirmbutton').on('click', function (e) { $("form").removeData("validator"); $("form").removeData("unobtrusiveValidation"); $.validator.unobtrusive.parse("form"); if (!$('form').valid()) { e.preventDefault(); return false; } var ordercustomer = $('#OrderId :selected', '#orderdetailformModal-body').text(); var productname = $('#ProductId :selected', '#orderdetailformModal-body').text(); var id = $('#Id', '#orderdetailformModal-body').val(); var productid = $('#ProductId :selected', '#orderdetailformModal-body').val(); var qty = $('#Qty', '#orderdetailformModal-body').val(); var price = $('#Price', '#orderdetailformModal-body').val(); var amount = $('#Amount', '#orderdetailformModal-body').val(); var orderid = $('#OrderId :selected', '#orderdetailformModal-body').val(); var orderdetail = { OrderCustomer: ordercustomer, ProductName: productname, Id: id, ProductId: productid, Qty: qty, Price: price, Amount: amount, OrderId: orderid, ObjectState: 'Added' } if (currentrowindex == '-1') { $orderdetailstable.bootstrapTable('append', orderdetail); } else { $orderdetailstable.bootstrapTable('updateRow', { index: currentrowindex, row: orderdetail }); } $('#orderdetailformModal').modal('toggle'); }); });</script> |
所有代码都是根据Entity 类型 和字段名进行生成,理论上针对业务系统都可以模板化,只要模式定下来什么代码都可以生成。
转自 http://www.cnblogs.com/neozhu/p/4322939.html
MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具的更多相关文章
- MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具集成Visual Studio 2013
MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具 经过一个多星期的努力总算完成了单表,多表关联(一对多,多对一)的增删改查的代码 ...
- RUF MVC5 Repositories Framework Generator代码生成工具介绍和使用
RUF MVC5 Repositories Framework Generator代码生成工具介绍和使用 功能介绍 这个项目经过了大半年的持续更新到目前的阶段基本稳定 所有源代码都是开源的,在gith ...
- Asp.net Webform 使用Repository模式实现CRUD操作代码生成工具
Asp.net Webform 使用Repository模式实现CRUD操作代码生成工具 介绍 该工具是通过一个github上的开源项目修改的原始作者https://github.com/Supere ...
- C# 代码生成工具 Millennials
Millennials 是一个可定制的 C# 代码生成工具,支持 MVC 和三层架构.ADO.NET.Nhibernate 和 LINQ. 项目主页:http://www.open-open.com/ ...
- Map工具系列-01-Map代码生成工具说明
所有cs端工具集成了一个工具面板 -打开(IE) Map工具系列-01-Map代码生成工具说明 Map工具系列-02-数据迁移工具使用说明 Map工具系列-03-代码生成BySQl工具使用说明 Map ...
- mybatis实战教程(mybatis in action)之九:mybatis 代码生成工具的使用
mybatis 应用程序,需要大量的配置文件,对于一个成百上千的数据库表来说,完全手工配置,这是一个很恐怖的工作量. 所以mybatis 官方也推出了一个mybatis代码生成工具的jar包. 今天花 ...
- 第二章 Mybatis代码生成工具
1.mybatis-generator作用 1).生成pojo 与 数据库结构对应 2).如果有主键,能匹配主键 3).如果没有主键,可以用其他字段去匹配 4).动态select,update,del ...
- 【C#】Excel做的数据表、SQLParameter代码生成工具
转载请注明出处http://www.cnblogs.com/Vulpers/ 做了一个小的代码生成工具,用于新建数据表时能够快速生成一些重复性很高的代码,目前仅支持SqlServer数据库及C#语言, ...
- 代码生成工具Database2Sharp中增加视图的代码生成以及主从表界面生成功能
在代码生成工具的各种功能规划中,我们一向以客户的需求作为驱动,因此也会根据需要增加一些特殊的功能或者处理.在实际的开发中,虽然我们一般以具体的表进行具体业务开发,但是有些客户提出有时候视图开发也是很常 ...
随机推荐
- 让自己的网站实现在线编辑office文档
我们可以通过Office Web Apps(OWA)来实现在线编辑word,excel,power point, one note,并集成到自己的网站里去. 1 准备工作 1.1 操作系统 安装了 ...
- ssh-key 与 git账户配置以及多账户配置,以及通信方式从https切换到ssh
参考:http://www.cnblogs.com/dubaokun/p/3550870.html 在使用git的时候,git与远程服务器是一般通过ssh传输的(也支持ftp,https),我们在管理 ...
- One Person Game ZOJ - 3329(期望dp, 数学)
There is a very simple and interesting one-person game. You have 3 dice, namely Die1, Die2 and Die3. ...
- mysql 单表卡死
由于单表数据量过大导致的更新操作处于卡死状态,无法打开也无法修改. 此时需要命令行模式连接数据库,注意点:此处连接需要相同的账号 1. $ SHOW PROCESSLIST; 2. $ kill 37 ...
- Codeforces Round #508 (Div. 2) C D
C: C - Gambling 给你两个数列 每一回合A可以选择从第一个序列里面选一个数或者清除第二个序列里面选一个数 同理B能从第二序列里面选数或者清除第一个序列里面一个数 然后 求A所选的数之和 ...
- poj3614 Sunscreen
贪心题. 如何找出正确的贪心策略呢? 我一开始是以为按照l排序,然后从1到n遍历,挑最大的满足的防晒霜.后来发现不行.挑最小的也不行. 看了题解发现是从n到1遍历. 为什么? 因为i-1的l比i的l承 ...
- [luogu1970][花匠]
题目地址 https://www.luogu.org/problemnew/show/P1970 题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定 把这排中的一部 ...
- Oracle 在JDBC中使用 存储过程,包
前提: 在Oracle中已经定义 存储过程 和 存储函数 和 包 导入了Oracle的JDBC jar 包 package demo; import java.sql.Connect ...
- unittest的使用三——断言
常用的断言有3种: 判断两个值是不是都相等,参数分别是第一个值,第二个值,msg代表不想等的话,描述的信息 def assertEqual(self, first, second, msg=None) ...
- NOIP 提高组 2014 联合权值(图论???)
传送门 https://www.cnblogs.com/violet-acmer/p/9937201.html 题解: 相关变量解释: int n; int fa[maxn];//fa[i] : i的 ...