65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (14投票s)

2012 年 1 月 23 日

CPOL

4分钟阅读

viewsIcon

120675

downloadIcon

119919

使用 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 应用,用户可以通过它与应用交互。

Design-Diagram.png

项目结构

Project-Stucture.png

实现细节

EF 4.1 数据库优先模型

MVCJqGridCrud 解决方案中,添加 DAL、BLL 和 Web 项目。

右键单击 DAL 项目,从上下文菜单中选择添加,然后从子菜单中选择新建项。

选择 ADO.NET 实体数据模型。

单击“添加”。

NewEntityDataModelDialog.png

在后续向导中,选择从数据库生成。

单击“下一步”。

EDMWizard-1.png

注意: 我在此演示中使用名为“ProgrammingEFDB1”的数据库,可在代码文件夹(可下载)中找到。它有两张表,contact address

向导的下一步将为您提供配置数据库连接的选项。

单击新建连接,然后从连接属性弹出窗口中选择所需的数据库。在本例中,它是 ProgrammingEFDB1

选中向导底部的复选框,该复选框声明“将实体连接设置保存在 App.Config 中”。

EDMWizard-2.png

单击“下一步”。

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

EDMWizard-3.png

Model1.edmx 将添加到 DAL 项目。

双击 Model1.edmx 以打开该文件的设计器视图。

在设计器视图中,右键单击并从上下文菜单中选择“添加代码生成项”。

从向导中选择 ADO.NET DbContext 生成器以使用简化的 DbContext API。

将向 DAL 项目添加两个项。

  • Model1.tt
    它包含模型中每个实体的 POCO 类。
  • Model1.Context.tt
    它派生自 DBContext ,用于查询和持久化数据。

t4TemplateGeneration_small.png

存储库

仓储介于域和数据映射层之间,就像内存中的域对象集合一样。仓储将域对象与数据库访问代码的详细信息隔离。

我使用了专门的仓储,这些仓储派生自具有重写或附加方法的通用仓储(基类)。通过这种方法,我可以受益于通用仓储中的常用方法,并在专用仓储中添加/重写专用方法。

在此演示中,我保留了可能的常用方法,例如 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.jsJqGrid 的 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 屏幕截图

UI-ScreenShot_small.png

结论

在附加的文件夹中找到代码,请不要忘记对本文进行评分或投票。此外,请添加您的评论以使其更好。

历史

  • 2012 年 1 月 22 日:初始版本
© . All rights reserved.