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 代码生成工具的更多相关文章

  1. MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具集成Visual Studio 2013

    MVC 5 Scaffolder + EntityFramework+UnitOfWork Pattern 代码生成工具 经过一个多星期的努力总算完成了单表,多表关联(一对多,多对一)的增删改查的代码 ...

  2. RUF MVC5 Repositories Framework Generator代码生成工具介绍和使用

    RUF MVC5 Repositories Framework Generator代码生成工具介绍和使用 功能介绍 这个项目经过了大半年的持续更新到目前的阶段基本稳定 所有源代码都是开源的,在gith ...

  3. Asp.net Webform 使用Repository模式实现CRUD操作代码生成工具

    Asp.net Webform 使用Repository模式实现CRUD操作代码生成工具 介绍 该工具是通过一个github上的开源项目修改的原始作者https://github.com/Supere ...

  4. C# 代码生成工具 Millennials

    Millennials 是一个可定制的 C# 代码生成工具,支持 MVC 和三层架构.ADO.NET.Nhibernate 和 LINQ. 项目主页:http://www.open-open.com/ ...

  5. Map工具系列-01-Map代码生成工具说明

    所有cs端工具集成了一个工具面板 -打开(IE) Map工具系列-01-Map代码生成工具说明 Map工具系列-02-数据迁移工具使用说明 Map工具系列-03-代码生成BySQl工具使用说明 Map ...

  6. mybatis实战教程(mybatis in action)之九:mybatis 代码生成工具的使用

    mybatis 应用程序,需要大量的配置文件,对于一个成百上千的数据库表来说,完全手工配置,这是一个很恐怖的工作量. 所以mybatis 官方也推出了一个mybatis代码生成工具的jar包. 今天花 ...

  7. 第二章 Mybatis代码生成工具

    1.mybatis-generator作用 1).生成pojo 与 数据库结构对应 2).如果有主键,能匹配主键 3).如果没有主键,可以用其他字段去匹配 4).动态select,update,del ...

  8. 【C#】Excel做的数据表、SQLParameter代码生成工具

    转载请注明出处http://www.cnblogs.com/Vulpers/ 做了一个小的代码生成工具,用于新建数据表时能够快速生成一些重复性很高的代码,目前仅支持SqlServer数据库及C#语言, ...

  9. 代码生成工具Database2Sharp中增加视图的代码生成以及主从表界面生成功能

    在代码生成工具的各种功能规划中,我们一向以客户的需求作为驱动,因此也会根据需要增加一些特殊的功能或者处理.在实际的开发中,虽然我们一般以具体的表进行具体业务开发,但是有些客户提出有时候视图开发也是很常 ...

随机推荐

  1. PhantomJS报错warnings.warn('Selenium support for PhantomJS has been deprecated, please use headless '

    原因:Selenuim已经放弃PhantomJS3.x了,建议使用火狐或者谷歌无头浏览器. 解决方法: 1.phantomjs降级,换个2.x版本的 2.使用无头浏览器,示例代码(自己改了改,如有错误 ...

  2. 动态逆序对[CDQ分治]

    题面 luogu cdq分治入门 注意删的是值不是位置! #include <cstdio> #include <algorithm> #include <cmath&g ...

  3. 【转】STM32: 一种计算CPU使用率的方法及其实现原理

    1  前言出于性能方面的考虑,有的时候,我们希望知道CPU的使用率为多少,进而判断此CPU的负载情况和对于当前运行环境是否足够“胜任”.本文将介绍一种计算CPU占有率的方法以及其实现原理. 2  移植 ...

  4. docker-compose.yml(4)

    实例3:version: '3'services: mysql: image: mysql network_mode: "host" environment: - MYSQL_RO ...

  5. 借网站日记分析~普及一下Pandas基础

      对网站日记分析其实比较常见,今天模拟演示一下一些应用场景,也顺便说说Pandas,图示部分也简单分析了下 1.数据清洗¶ 一般数据都不可能直接拿来用的,或多或少都得清理一下,我这边就模拟一下清洗完 ...

  6. InnoDB,5项最佳实践,知其所以然?

    InnoDB,5项最佳实践,知其所以然? 原创: 58沈剑 架构师之路 昨天 缓存讲了一个月<缓存架构,一篇足够>.今天,开始写数据库. 第一篇,说说MySQL两个最常用的存储引擎,MyI ...

  7. 如何写一个通用的README规范

    背景 我们平常在进行项目开发时,一般都会把代码上传至代码托管平台上方便管理和维护.目前我厂使用的托管平台是SVN,国内外还有一些比较知名的代码托管平台,比如github.Gitlab.BitBucke ...

  8. 内部git常用总结

    上库git常用命令总结   http://3ms.huawei.com/hi/group/1531/wiki_4955279.html?for_statistic_from=all_group_wik ...

  9. 将本地html文件拖到IE8浏览器无法打开,直接弹出一个下载的对话框

    查看一下注册表[HKEY_CLASSES_ROOT\.htm]和[HKEY_CLASSES_ROOT\.html]的ContentType值是否都为“text/html”

  10. 表格中的checkbox复选框 全选非全选 公共方法 及提交选中结果

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...