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 = ;
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 = , int limit = , string search = "", string sort = "", string order = "")
{
int totalCount = ;
int pagenum = offset / limit + ;
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 <= )
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编辑子表数据代码
<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 类型 和字段名进行生成,理论上针对业务系统都可以模板化,只要模式定下来什么代码都可以生成。
MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具集成Visual Studio 2013的更多相关文章
- MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具
MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具集成Visual Studio 2013 MVC 5 Scaffolder + ...
- Visual Studio 2013 无法创建MVC项目,系统找不到指定的文件.(Exception from HRESULT:08x0070002)
在Visual Studio 2013中创建新MVC项目,(PS:现在创建个MVC项目,差点都找不到在哪,汗!-) 确定后提示,系统找不到指定的文件.(Exception from HRESULT:0 ...
- Visual Studio 2013下JSON可视化工具
Visual Studio 2013现在我们有个小工具可以实现JSON可视化,这样给我们调试JSON提供了便利. JSON这种数据格式已经比较流行,在WEB前端随处可见. 在你需要安装VS ...
- Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用
Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用 Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.cs ...
- Visual Studio 2013 Preview - ASP.NET, MVC 5, Web API 2新功能搶先看
Visual Studio 2013 Preview - ASP.NET, MVC 5, Web API 2新功能搶先看 來自TechEd North America 2013的第一手消息 以下資訊均 ...
- Visual Studio 2013编辑器+SourceTree代码管理工具及扩展工具
Visual Studio 2013: 美国微软公司的编辑开发工具 扩展工具: Resharper:进行深度代码分析,函数深度查询(ctrl+鼠标左): Grunt:是基于Node.js的项目以自动化 ...
- 【MVC 4】4.MVC 基本工具(Visual Studio 的单元测试、使用Moq)
作者:[美]Adam Freeman 来源:<精通ASP.NET MVC 4> 3.Visual Studio 的单元测试 有很多.NET单元测试包,其中很多是开源和免费的.本 ...
- MVC 基本工具(Visual Studio 的单元测试、使用Moq)
3.Visual Studio 的单元测试 有很多.NET单元测试包,其中很多是开源和免费的.本文打算使用 Visual Studio 附带的内建单元测试支持,但其他一些.NET单元测试包也是可用的. ...
- Win10开发必备工具:Visual Studio 2015正式版下载
7月21日凌晨最新消息,面向大众用户的Visual Studio 2015集成开发工具正式版免费试用版已经推出.本文帮大家汇总一下简体中文社区版.专业版以及企业版在线安装版以及ISO离线安装镜像下载地 ...
随机推荐
- playframework 一步一步来 之 日志 (二)
带着之前的疑问,我们先回顾一下日志相关的知识: 首先是SL4J,SL4J是个什么东西来着?官方解释为:“The Simple Logging Facade for Java (SLF4J) serve ...
- vc++ openssl 程序签名
RSA一般有两种应用场景: 1.公钥加密.私钥解密:这是数据安全通信领域最常见情形: 2.私钥加验.公钥验签:这主要用于数字签名. 我们这里用到的是第二种情况: 这里是基于OpenSSL,首先 ...
- 《C#从现象到本质》读书笔记(四)第4章C#和面向对象
<C#从现象到本质>读书笔记第4章C#和面向对象 面向对象程序设计OOP 面向对象的三大特性是: 1)封装:类可以将它的成员私有化,只暴露它认为应当暴露给外界的成员.通过私有化成员,外界不 ...
- delete,truncate ,drop区别
use [database_name]go delete from table_nameTest where FCRTime<(Select CONVERT(varchar(100),DATE ...
- com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax;问题的解决
哇,时隔两天时间,终于找到这个问题的解决办法,先看问题 这是我最近写的家庭记账本网页版,按顺序输入点击保存,总是弹出添加失败的提示 顺着找原因,把原因锁定在dao层的sql语句上,反复检查,没有找到一 ...
- 2019.03.01 bzoj3075: [Usaco2013]Necklace(kmp+dp)
传送门 题意简述:给出S,TS,TS,T两个字串,∣S∣≤10000,∣T∣≤1000|S|\le10000,|T|\le1000∣S∣≤10000,∣T∣≤1000,问至少从SSS中删去几个字符能够 ...
- python中 os._exit() 和 sys.exit(), exit(0)和exit(1) 的用法和区别
os._exit() 和 sys.exit() os._exit() vs sys.exit() 概述 Python的程序有两中退出方式:os._exit(), sys.exit().本文介绍这两种方 ...
- 02-jQuery的选择器
我们以前在CSS中学习的选择器有: 今天来学习一下jQuery 选择器. jQuery选择器是jQuery强大的体现,它提供了一组方法,让我们更加方便的获取到页面中的元素. 1.jQuery 的基本选 ...
- 第一个Python小爬虫
这个爬虫是参考http://python.jobbole.com/81353/这篇文章写的 这篇文章可能年代过于久远,所以有些代码会报错,然后我自己稍微修改了一下,增加了一个getContentAll ...
- 卷积在深度学习中的作用(转自http://timdettmers.com/2015/03/26/convolution-deep-learning/)
卷积可能是现在深入学习中最重要的概念.卷积网络和卷积网络将深度学习推向了几乎所有机器学习任务的最前沿.但是,卷积如此强大呢?它是如何工作的?在这篇博客文章中,我将解释卷积并将其与其他概念联系起来,以帮 ...