ASP.NET MVC-3.0/ JqGrid/ 工作单元/ 仓储/ EF 4.1 CRUD 应用 (N 层)






4.85/5 (14投票s)
使用 ASP.NET MVC 3.0/ JqGrid/ 工作单元/ 仓储/ EF 4.1 设计多层 Web 应用操作,并演示如何使用它执行 CRUD 操作的代码。
引言
在本文中,我将演示如何使用 ASP.NET MVC 3.0/ JqGrid/ 工作单元/ 仓储/ EF 4.1 设计多层 Web 应用操作,然后演示如何使用它执行 CRUD 操作的代码。
我假设您对 ASP.NET MVC/JqGrid/Jquery 和 EF 4.1 有基本了解。
设计
- DAL: 数据访问层包含仓储和 EF 4.1 生成的代码,用于处理与底层数据存储和实体交互。
- BLL: 业务逻辑层包含合并应用业务规则的类。此外,此层中使用工作单元模式来跟踪可能影响数据库的所有更改。
- Web 应用: 这是一个基于 ASP.NET MVC 的 Web 应用,用户可以通过它与应用交互。
项目结构
实现细节
EF 4.1 数据库优先模型
在 MVCJqGridCrud
解决方案中,添加 DAL、BLL 和 Web 项目。
右键单击 DAL 项目,从上下文菜单中选择添加,然后从子菜单中选择新建项。
选择 ADO.NET 实体数据模型。
单击“添加”。

在后续向导中,选择从数据库生成。
单击“下一步”。

注意: 我在此演示中使用名为“ProgrammingEFDB1
”的数据库,可在代码文件夹(可下载)中找到。它有两张表,contact
和 address
。
向导的下一步将为您提供配置数据库连接的选项。
单击新建连接,然后从连接属性弹出窗口中选择所需的数据库。在本例中,它是 ProgrammingEFDB1
。
选中向导底部的复选框,该复选框声明“将实体连接设置保存在 App.Config 中”。

单击“下一步”。
在向导的下一步中,仅为此演示选择表,并选中底部的复选框,然后单击完成。

Model1.edmx 将添加到 DAL 项目。
双击 Model1.edmx 以打开该文件的设计器视图。
在设计器视图中,右键单击并从上下文菜单中选择“添加代码生成项”。
从向导中选择 ADO.NET DbContext
生成器以使用简化的 DbContext
API。
将向 DAL 项目添加两个项。
- Model1.tt
它包含模型中每个实体的 POCO 类。 - Model1.Context.tt
它派生自DBContext
,用于查询和持久化数据。
存储库
仓储介于域和数据映射层之间,就像内存中的域对象集合一样。仓储将域对象与数据库访问代码的详细信息隔离。
我使用了专门的仓储,这些仓储派生自具有重写或附加方法的通用仓储(基类)。通过这种方法,我可以受益于通用仓储中的常用方法,并在专用仓储中添加/重写专用方法。
在此演示中,我保留了可能的常用方法,例如 GetById()
、Add()
在基本仓储中。同时,更专业的名为 GetContactsPaged()
的方法与联系人仓储相关,位于 Contact
仓储中。
RepositoryBase.cs (通用仓储类)
public abstract class RepositoryBase<T> where T : class
{
internal ProgrammingEFDB1Entities _dataContext;
internal DbSet<T> _dbset;
public RepositoryBase(ProgrammingEFDB1Entities context)
{
this._dataContext = context;
this._dbset = context.Set<T>();
}
public virtual List<T> Get(
Expression<Func<T, bool>> filter = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
string includeProperties = "")
{
IQueryable<T> query = _dbset;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
_dbset.Remove(entity);
}
public virtual void Delete(Expression<Func<T, bool>> where)
{
IEnumerable<T> objects = _dbset.Where<T>(where).AsEnumerable();
foreach (T obj in objects)
_dbset.Remove(obj);
}
public virtual T GetById(long id)
{
return _dbset.Find(id);
}
public virtual T GetById(string id)
{
return _dbset.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return _dbset.ToList();
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return _dbset.Where(where).ToList();
}
public T Get(Expression<Func<T, bool>> where)
{
return _dbset.Where(where).FirstOrDefault<T>();
}
}
ContactRepository.cs
public class ContactRepository : RepositoryBase<Contact>
{
public ContactRepository(ProgrammingEFDB1Entities context)
: base(context)
{
}
public List<Contact> GetContactPaged(int page, int rows, out int totalCount)
{
totalCount = _dataContext.Contacts.Count();
return _dataContext.Contacts.OrderBy(c => c.ContactID).Skip
(page * rows).Take(rows).ToList();
}
}
工作单元
工作单元跟踪您在可能影响数据库的业务事务期间所做的一切。我认为,工作单元有点类似于事务。它只是封装了单个业务操作。在此演示中,我确保每个业务操作都有一个新的 DBContext
。调用 unitofwork.save()
方法时,它将提交当前 DBContext
中的更改。
UnitofWork.cs
public class UnitOfWork : IDisposable
{
private ProgrammingEFDB1Entities _context;
public UnitOfWork()
{
_context = new ProgrammingEFDB1Entities();
}
private ContactRepository _contactRepository;
public ContactRepository ContactRepository
{
get
{
if (this._contactRepository == null)
{
this._contactRepository = new ContactRepository(_context);
}
return _contactRepository;
}
}
public void Save()
{
_context.SaveChanges();
}
private bool _disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this._disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
业务逻辑层
它封装了应用程序的业务逻辑。在代码演示中,为了简单起见,我只使用了一个名为 ManageContacts.cs 的类。它使用工作单元模式进行应用程序业务操作。
ManageContacts.cs
public class ManageContacts
{
public IEnumerable<Contact> GetContacts()
{
IEnumerable<Contact> contacts;
using (UnitOfWork unitOfWork = new UnitOfWork())
{
contacts = unitOfWork.ContactRepository.GetAll();
}
return contacts;
}
public bool AddContact(Contact contact)
{
using (UnitOfWork unitOfWork = new UnitOfWork())
{
unitOfWork.ContactRepository.Add(contact);
unitOfWork.Save();
}
return true;
}
public bool UpdateContact(Contact contact, int id)
{
using (UnitOfWork unitOfWork = new UnitOfWork())
{
var contactEntity = unitOfWork.ContactRepository.GetById(id);
contactEntity.Title = contact.Title;
contactEntity.FirstName = contact.FirstName;
contactEntity.LastName = contact.LastName;
contactEntity.ModifiedDate = DateTime.Now;
unitOfWork.Save();
}
return true;
}
public bool DeleteContact(int id)
{
using (UnitOfWork unitOfWork = new UnitOfWork())
{
Contact contact = unitOfWork.ContactRepository.GetById(id);
unitOfWork.ContactRepository.Delete(contact);
unitOfWork.Save();
}
return true;
}
public List<Contact> GetContactPaged(int page, int rows, out int totalCount)
{
List<Contact> contacts;
using (UnitOfWork unitOfWork = new UnitOfWork())
{
contacts = unitOfWork.ContactRepository.GetContactPaged
(page, rows, out totalCount);
}
return contacts;
}
public Contact GetById(int id)
{
Contact contact;
using (UnitOfWork unitOfWork = new UnitOfWork())
{
contact = unitOfWork.ContactRepository.GetById(id);
}
return contact;
}
}
控制器 (Controller)
ASP.NET MVC 控制器协调 UI 和模型(数据模型)之间的关系。
以下操作方法已添加到我们的应用程序中。
GridDemoData()
: 它将以 JSON 格式将联系人数据返回到 UI 层以进行 JqGrid 绑定,并处理用户输入以进行分页。PerformCRUDOperation()
: 它通过 JqGrid UI 处理来自用户的 CRUD 输入。
HomeController.cs
public ActionResult GridDemoData(int page, int rows,
string search, string sidx, string sord)
{
var manageContacts = new ManageContacts();
int currentPage = Convert.ToInt32(page) - 1;
int totalRecords = 0;
var data = manageContacts.GetContactPaged
(currentPage, rows, out totalRecords);
var totalPages = (int)Math.Ceiling(totalRecords / (float)rows);
var jsonData = new
{
total = totalPages,
page,
records = totalRecords,
rows = (
from m in data
select new
{
id = m.ContactID,
cell = new object[]
{
m.Title,
m.FirstName,
m.LastName
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
public ActionResult PerformCRUDAction(Contact contact)
{
var manageContacts = new ManageContacts();
bool result = false;
switch (Request.Form["oper"])
{
case "add":
contact.AddDate = DateTime.Now.Date;
contact.ModifiedDate = DateTime.Now;
result = manageContacts.AddContact(contact);
break;
case "edit":
int id = Int32.Parse(Request.Form["id"]);
result = manageContacts.UpdateContact(contact,id);
break;
case "del":
id = Int32.Parse(Request.Form["id"]);
result = manageContacts.DeleteContact(id);
break;
default:
break;
}
return Json(result);
}
视图(UI 层)
JqGrid 设置要求
以下代码用于 site.master
中的 JqGrid 设置。
<link href="<%= ResolveUrl("~/Content/themes/flick/ui.jqgrid.css") %>" rel="stylesheet"
type="text/css" />
需要在 index.aspx 中添加以下 HTML 代码用于 JqGrid
。
<div id="myDiv" style="width: 100%">
<table id="grid" cellpadding="0" cellspacing="0">
</table>
<div id="pager" name="pager" style="text-align: center;">
</div>
</div>
以下是 JqGridCRUD.js 中 JqGrid
的 JavaScript 代码。
var lastsel;
$(function () {
$("#grid").jqGrid({
colNames: ['Title', 'First Name', 'Last Name'],
colModel: [
{ name: 'Title', index: 'Title', sortable: false,
align: 'left', width: '200',
editable: true, edittype: 'text'
},
{ name: 'FirstName', index: 'FirstName', sortable: false,
align: 'left', width: '200',
editable: true, edittype: 'text'
},
{ name: 'LastName', index: 'LastName', sortable: false,
align: 'left', width: '200',
editable: true, edittype: 'text'
}
],
pager: jQuery('#pager'),
sortname: 'FirstName',
rowNum: 10,
rowList: [10, 20, 25],
sortorder: "",
height: 225,
viewrecords: true,
rownumbers: true,
caption: 'Contacts',
imgpath: '/Content/jqGridCss/smoothness/images',
width: 750,
url: "/Home/GridDemoData",
editurl: "/Home/PerformCRUDAction",
datatype: 'json',
mtype: 'GET',
onCellSelect: function (rowid, iCol, aData) {
if (rowid && rowid !== lastsel) {
if (lastsel)
jQuery('#grid').jqGrid('restoreRow', lastsel);
jQuery('#grid').jqGrid('editRow', rowid, true);
lastsel = rowid;
}
}
})
jQuery("#grid").jqGrid('navGrid', '#pager',
{ edit: false, add: true, del: true, search: false, refresh: true },
{ closeOnEscape: true, reloadAfterSubmit: true,
closeAfterEdit: true, left: 400, top: 300 },
{ closeOnEscape: true, reloadAfterSubmit: true,
closeAfterAdd: true, left: 450, top: 300, width: 520 },
{ closeOnEscape: true, reloadAfterSubmit: true, left: 450, top: 300 });
});
UI 屏幕截图

结论
在附加的文件夹中找到代码,请不要忘记对本文进行评分或投票。此外,请添加您的评论以使其更好。
历史
- 2012 年 1 月 22 日:初始版本