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中增加视图的代码生成以及主从表界面生成功能
在代码生成工具的各种功能规划中,我们一向以客户的需求作为驱动,因此也会根据需要增加一些特殊的功能或者处理.在实际的开发中,虽然我们一般以具体的表进行具体业务开发,但是有些客户提出有时候视图开发也是很常 ...
随机推荐
- 洛谷AT2342 Train Service Planning(思维,动态规划,珂朵莉树)
洛谷题目传送门 神仙思维题还是要写点东西才好. 建立数学模型 这种很抽象的东西没有式子描述一下显然是下不了手的. 因为任何位置都以\(k\)为周期,所以我们只用关心一个周期,也就是以下数都在膜\(k\ ...
- 【BZOJ2242】计算器(BSGS,快速幂)
[BZOJ2242]计算器(BSGS,快速幂) 题面 BZOJ 洛谷 1.给定y.z.p,计算y^z mod p 的值: 2.给定y.z.p,计算满足xy ≡z(mod p)的最小非负整数x: 3.给 ...
- 【AtCoder3611】Tree MST(点分治,最小生成树)
[AtCoder3611]Tree MST(点分治,最小生成树) 题面 AtCoder 洛谷 给定一棵\(n\)个节点的树,现有有一张完全图,两点\(x,y\)之间的边长为\(w[x]+w[y]+di ...
- 【UNR #1】火车管理
题目描述 uoj 旗下有一个火车站,用来管理属于 uoj 的小火车. 火车站一共有 nn 条编号为 1,…,n1,…,n 的,只有一端的用来存放小火车的铁路,由于小火车特殊的构造,每条铁路可以停放无数 ...
- django(八)之数据库表的一对多,多对多表-增删改查
单表操作 表记录的添加 方式一: Book() b=Book(name="python基础",price=99,author="yuan",pub_date=& ...
- 千人基因组(1000 Genomes)提取群体(population)或者样本(sample ID)信息
进入链接:http://www.internationalgenome.org/data-portal/sample 点击“filter by population”,在弹出的选择框里,选择想要下载的 ...
- 第三节,使用OpenCV 3处理图像(模糊滤波、边缘检测)
一 不同色彩空间的转换 OpenCV中有数百种关于在不同色彩空间之间转换的方法.当前,在计算机中有三种常用的色彩空间:灰度,BGR以及HSV(Hue,Saturation,Value). 灰度色彩空间 ...
- jmeter的介绍和使用二
三. 1.http的请求默认值 当一个项目有多个模块,他们的host都是一致的,为了不重复的写host或者当某一天host变了,只需要修改一个地方就好.比如下面的两个请求,可以把host分离出来,所以 ...
- macs 学习
点击 首先andriomianfest主配文件(主要配置文件),来启动主要的activity对象,然后通过该对象调用create方法来加载布局文件xml active通过布局文件的控件生成相应的对象. ...
- js解析base64
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ...