摘要
本文中,我将展示使用基于asp.net mvc3+EF来操作JQGrid制作表格
假设你了解ASP.NET MVC3.0与EF4.x的配合操作
下载地址
分层设计
- DAL: 数据访问层包含repositories和EF4.x的代码, 该层所做事务直接操作数据库,针对数据的增、删、改、查。
- BLL: 针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。.
- Web UI层:职责是数据的展现和采集,数据采集的结果通常以Entity object提交给BL层处理。Service Interface侧层用于将业务或数据资源发布为服务(如WebServices)。

项目结构

实现细节


注意:我使用的数据库名为“ProgrammingEFDB1”这个演示,下载的数据库文件中,它有两个表,contact 和address。
下一步的向导将给你的选项来配置您的数据库连接。
单击新的连接并选择您想要的数据库连接属性弹出。在本例中,它是ProgrammingEFDB1。
选中该复选框在底部的向导即“保存数据链接到app.config“。
点击下一步
选中数据库的表和复选框,点击完成按钮
Model1.edmx必须放在DAL层中
双击Model1。edmx打开文件的设计视图。
在设计视图中,右击并从上下文菜单中选择“添加代码生成项目”。
Model1.tt有2种代码生成模式,第一种为POCO代码简介,第二为DBContext
- Model1.tt
It contains POCO classes for each entity in your model. - Model1.Context.tt
It derived fromDBContext
to use for querying and persisting data.
容器(Repository)
repository就是一个管理数据持久层的,它负责数据的CRUD(Create, Read, Update, Delete)
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();
}
}
事务
简单性
和数据据事务差不多的快
独立于数据库,不同数据库的专有代码被隐藏了
缺点:
事务不能跨越多个数据库连接
事务执行在数据库连接层上,所以需要在事务过程中维护一个数据库连接
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
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 Controller对象的职责是传递数据,获取View对象(实现了IView接口的类),通知View对象显示.
View对象的作用是显示.虽然显示的方法RenderView()是由Controller调用的,
但是Controller仅仅是一个"指挥官"的作用, 具体的显示逻辑仍然在View对象中
GridDemoData()
:返回Json数据给JQgrid绑定PerformCRUDOperation()
: 处理用户传递的操作
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);
}
View (UI Layer)
JqGrid Setup Requirements
The following code is used for JqGrid setup in site.master
.
<link href="<%= ResolveUrl("~/Content/themes/flick/ui.jqgrid.css") %>" rel="stylesheet"
type="text/css" />
Following HTML code need to be added in index.aspx for
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>
Below is the JavaScript code for
JqGrid
in
JqGridCRUD.js
.
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 });
});
效果显示
