4.在MVC中使用仓储模式进行增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-using-the-repository-pattern-in-mvc/
或者:http://www.codeproject.com/Articles/644605/CRUD-Operations-Using-the-Repository-Pattern-in-MV
系列目录:
- Relationship in Entity Framework Using Code First Approach With Fluent API【【使用EF Code-First方式和Fluent API来探讨EF中的关系】】
- Code First Migrations with Entity Framework【使用EF 做数据库迁移】
- CRUD Operations Using Entity Framework 5.0 Code First Approach in MVC【在MVC中使用EF 5.0做增删查改】
- CRUD Operations Using the Repository Pattern in MVC【在MVC中使用仓储模式,来做增删查改】
- CRUD Operations Using the Generic Repository Pattern and Unit of Work in MVC【在MVC中使用泛型仓储模式和工作单元来做增删查改】
- CRUD Operations Using the Generic Repository Pattern and Dependency Injection in MVC【在MVC中使用泛型仓储模式和依赖注入,来做增删查改】
上一篇文章,讲到了MVC中基本的增删查改,这篇文章,我会继续说到,使用仓储模式,进行增删查改。
什么是仓储模式呢,我们先来了解一下:
仓储模式是为了在程序的数据访问层和业务逻辑层之间创建一个抽象层,它是一种数据访问模式,提供了一种更松散耦合的数据访问方法。我们把创建数据访问的逻辑代码写在单独的类中,或者类库中,这就是仓储。仓储负责和业务层进行持久化通信。在这篇文章中,我将会实现一个单一的业务模型的方法,来设计仓储模式-----这个仓储模式对于每一个实体都有一个仓储类。对于Book实体,我将会创建一个仓储接口和一个仓储类。当我们在控制器中初始化仓储的时候,我们使用仓储接口,所以控制器就会接受,任何实现了这个仓储接口的对象的引用。当控制器运行在Web服务器下的时候,它会接受一个和EF协同工作的仓储。MVC的控制器和仓储协同工作,去加载并持久化业务层。接着利用依赖注入,仓储能够被注射到控制器的构造函数中去。下面的图表,显示了仓储和EF数据上下文之间的关系,在这里,MVC控制器和仓储直接协同工作,而不是和EF。

那什么是EF呢,我们也来简单的了解一下吧:
EF是一个包含在.NET Framework中的ORM框架。它可以根据数据库表,生成业务对象和业务实体。它提供了基本的增删查改的功能。它可以很好的管理实体之间的关系。有了EF,我们可以直接和实体模型相互协同工作,而不用和关系数据库模型直接交互。这个抽象层,允许我们去专注于业务层的行为,还有实体之间的关系。我们使用EF数据上下文,进行查询数据。当增删查改中的某个操作被触发的时候,EF就会生成必要的SQL去执行这个操作。
EF处理数据的方式?
EF允许开发者,选择Database First【数据库优先】,Model First【模型优先】,Code First【代码优先】中的任何一个方式。
DataBase First【数据库优先】
数据库优先:是基于现有的数据库上的,以数据为中心的设计。EF能够基于数据库中的表和列生成业务实体。我们数据库的结构信息,都存储在一个后缀名为.edmx的文件中,存储的形式是XML。

Model First【模型优先】
在模型优先中,我们事先并不存在数据库,并且EF为我们提供了设计器,我们可以用来设计概念上的模型。模型优先同样使用后缀名为.edmx的文件来存储模型和映射信息。当我们的实体模型被创建好之后,EF设计器就可以为我们生成数据库。

Code First【代码优先】
在这个代码优先中,不管你是不是已经有数据库了,你都可以根据表和列,来创建你自己的实体。然后使用EF【不带后缀名为.edmx】。在代码优先的方式中,EF不使用任何形式的配置文件(.edmx文件)来存储数据库,因为EF中的Mapping API使用了约定,在运行的时候,会动态为我们创建数据库。

EF 6.0中已经开始支持存储过程了:参考文章《Entity Framework 6 Code First新特性:支持存储过程》
在这篇文章中,我会使用EF Code First在程序中开发一个数据访问层。这背后的推动力量是使用POCO (Plain Old CLR Objects) 类。Code First使用一系列的约定,来映射POCO类,但是这可以通过Code First数据注解来改变。
好了,理论知识将的差不多了,现在开始将今天的正题吧:
首先看看项目结构:

我们需要在空白的资源解决方案基础上,添加两个类库EF.Data、EF.Entity、还有一个空白MVC模板的EF.Web 项目;三个项目之间的引用关系,就是EF.Data需要引用EF.Entity,EF.Web项目需要引用EF.Data和EF.Entity两个类库。然后,EF.Data和EF.Web项目都需要引入EF框架。
这里我为了方便大家理解,也为了简单起见,就只添加一个实体Book:
下面看看EF.Entity类库中的Book实体代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.Entity
{
public class Book:BaseEntity
{
/// <summary>
/// 书名
/// </summary>
public string BookTitle { get; set; } /// <summary>
/// 价格
/// </summary>
public decimal Price { get; set; } /// <summary>
/// 出版商
/// </summary>
public string PublisherName { get; set; } /// <summary>
/// 出版时间
/// </summary>
public DateTime PublishedDate { get; set; }
}
}
BaseEntity实体:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.Entity
{
public abstract class BaseEntity
{
/// <summary>
/// 编号
/// </summary>
public int ID { get; set; } /// <summary>
/// 添加时间
/// </summary>
public DateTime AddedDate { get; set; } /// <summary>
/// 修改时间
/// </summary>
public DateTime ModifiedDate { get; } }
}
EF.Data类库中BookMap实体:
using EF.Entity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.Data
{
public class BookMap:EntityTypeConfiguration<Book>
{
public BookMap()
{
//配置主键
this.HasKey(s => s.ID); //配置列
this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(s => s.BookTitle).HasColumnType("NVARCHAR").HasMaxLength().IsRequired();
this.Property(s => s.PublisherName).HasColumnType("nvarchar").HasMaxLength(50).IsRequired();
this.Property(s => s.Price).IsRequired();
this.Property(s => s.AddedDate).IsRequired();
this.Property(s => s.ModifiedDate).IsOptional();
this.Property(s => s.PublishedDate).IsRequired(); //配置表
this.ToTable("Books"); }
}
}
实体和映射类弄完了,开始写EF数据上下文类:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks; namespace EF.Data
{
public class EFDbContext:DbContext
{
public EFDbContext()
: base("name=DbConnectionString")
{ } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => !String.IsNullOrEmpty(type.Namespace))
.Where(type => type.BaseType != null && type.BaseType.IsGenericType
&& type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in typesToRegister)
{
dynamic configurationInstance = Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
} }
}
}
连接字符串:【EF.Data和EF.Web项目都要添加】
<connectionStrings>
<add name="DbConnectionString" connectionString="Server=.;Database=BookDB;uid=sa;Pwd=Password_1" providerName="System.Data.SqlClient"/>
</connectionStrings>
弄完之后,我们先来开启数据库迁移技术吧:
在程序包管理器控制台下输入:
Enable-Migrations

然后修改生成的Configuration类:

最后在程序管理器控制台输入:
Update-Database -Verbose

可以看到生成的数据库的SQL语句了。看下数据库:

数据库生成了,现在开始创建仓储模式,来进行增删查改吧:
using EF.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.Data
{
public interface IRepository
{
/// <summary>
/// 获取所有的Book
/// </summary>
/// <returns></returns>
IEnumerable<Book> GetAllBooks(); /// <summary>
/// 根据BookId查找Book
/// </summary>
/// <param name="bookId"></param>
/// <returns></returns>
Book GetBookById(int bookId); /// <summary>
/// 添加Book
/// </summary>
/// <param name="model"></param>
void InsertBook(Book model); /// <summary>
/// 修改Book
/// </summary>
/// <param name="model"></param>
void UpdateBook(Book model); /// <summary>
/// 删除Book
/// </summary>
/// <param name="bookId"></param>
void DeleteBook(int bookId); /// <summary>
/// 保存
/// </summary>
void Save();
}
}
BookRepository类:
using EF.Entity;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.Data
{
public class BookRepository:IRepository
{
private EFDbContext db;
public BookRepository()
{
db = new EFDbContext();
} public IEnumerable<Book> GetAllBooks()
{
return db.Set<Book>().ToList();
//throw new NotImplementedException();
} public Book GetBookById(int bookId)
{
return db.Set<Book>().Find(bookId);
//throw new NotImplementedException();
} public void InsertBook(Book model)
{
db.Entry(model).State = EntityState.Added;
//throw new NotImplementedException();
} public void UpdateBook(Book model)
{
db.Entry(model).State = EntityState.Modified;
//throw new NotImplementedException();
} public void DeleteBook(int bookId)
{
Book model= db.Set<Book>().Find(bookId);
db.Entry(model).State = EntityState.Deleted; //throw new NotImplementedException();
} public void Save()
{
db.SaveChanges();
//throw new NotImplementedException();
}
}
}
Book控制器代码:
using EF.Data;
using EF.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace EF.Web.Controllers
{
public class BookController : Controller
{
private IRepository _bookRepository;
public BookController()
{
this._bookRepository = new BookRepository();
}
// GET: Book
#region Index
public ActionResult Index()
{
return View(_bookRepository.GetAllBooks().ToList());
}
#endregion #region InsertBook
public ActionResult InsertBook()
{
return View();
} [HttpPost]
public ActionResult InsertBook(Book model)
{ _bookRepository.InsertBook(model);
_bookRepository.Save();
return RedirectToAction("Index");
}
#endregion #region UpdateBook
public ActionResult UpdateBook(int bookId)
{ Book model = _bookRepository.GetBookById(bookId);
if (model != null)
{
return View(model);
}
else
{
return View();
} } [HttpPost]
public ActionResult UpdateBook(Book model)
{
_bookRepository.UpdateBook(model);
_bookRepository.Save();
return RedirectToAction("Index");
}
#endregion #region BookDetails
public ActionResult BookDetails(int bookId)
{
Book model = _bookRepository.GetBookById(bookId);
if (model != null)
{
return View(model);
}
else
{
return View();
} }
#endregion #region DeleteBook
public ActionResult DeleteBook(int bookId)
{ Book model = _bookRepository.GetBookById(bookId);
if (model != null)
{
return View(model);
}
else
{
return View();
}
} [HttpPost]
public ActionResult DeleteBook(int bookId, FormCollection form)
{
_bookRepository.DeleteBook(bookId);
_bookRepository.Save();
return RedirectToAction("Index");
}
#endregion
}
}
具体的视图,根据模板生成。
修改一下默认的路由:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace EF.Web
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Book", action = "Index", id = UrlParameter.Optional }
);
}
}
}
运行项目:

添加玩数据之后:



这样就完成了使用仓储模式,进行增删查改的操作了。
最后看下项目完成之后的结构吧:

4.在MVC中使用仓储模式进行增删查改的更多相关文章
- python中关于list列表的增删查改操作
python中list的操#python创建列表的时候,会以堆栈的形式存放数据,从右向左往堆栈中存放数据 movies=["The holy Grail","The li ...
- mysql中数据表记录的增删查改(2)
select `数据表.字段1`, group_concat(`数据表.字段2`) from `数据表` group by `数据表.字段1` order by `数据表.字段1` desc; sel ...
- mysql中数据表记录的增删查改(1)
数据记录的增删改查 insert into `数据表名称` (`字段名称`, ...) values ('1', ...); delete from `数据表名称` where 子句; update ...
- 5.在MVC中使用泛型仓储模式和工作单元来进行增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...
- 在MVC中使用泛型仓储模式和工作单元来进行增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...
- 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...
- 在MVC中使用泛型仓储模式和依赖注入实现增删查改
标签: 原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository ...
- C# 动态生成word文档 [C#学习笔记3]关于Main(string[ ] args)中args命令行参数 实现DataTables搜索框查询结果高亮显示 二维码神器QRCoder Asp.net MVC 中 CodeFirst 开发模式实例
C# 动态生成word文档 本文以一个简单的小例子,简述利用C#语言开发word表格相关的知识,仅供学习分享使用,如有不足之处,还请指正. 在工程中引用word的动态库 在项目中,点击项目名称右键-- ...
- backbonejs mvc框架的增删查改实例
一:开发环境 coffeescript和nodejs需要先安装,没装网上自己查安装步骤. 代码编写环境及esp框架下载: esp框架下载地址:https://github.com/nonocast/e ...
随机推荐
- CRL快速开发框架系列教程十(导出对象结构)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- dagger2系列之Scope
Dagger的Scope注解代表的是作用域,通过实现自定义@Scope注解,标记当前生成对象的使用范围,标识一个类型的注射器只实例化一次,在同一个作用域内,只会生成一个实例, 然后在此作用域内共用一个 ...
- wordpress优化之结合prism.js为编辑器自定义按钮转化代码
原文链接 http://ymblog.net/2016/07/24/wordpress-prism/ 继昨天花了一天一夜的时间匆匆写了主题Jiameil3.0之后,心中一直在想着优化加速,体验更好,插 ...
- 用MongoDB分析合肥餐饮业
看了<从数据角度解析福州美食>后难免心痒,动了要分析合肥餐饮业的念头,因此特地写了Node.js爬虫爬取了合肥的大众点评数据.分析数据库我并没有采用MySQL而是用的MongoDB,是因为 ...
- “老坛泡新菜”:SOD MVVM框架,让WinForms焕发新春
火热的MVVM框架 最近几年最热门的技术之一就是前端技术了,各种前端框架,前端标准和前端设计风格层出不穷,而在众多前端框架中具有MVC,MVVM功能的框架成为耀眼新星,比如GitHub关注度很高的Vu ...
- jquery.each()
$(selector).each(function(index,element)) index - 选择器的 index 位置 element - 当前的元素(也可使用 "this" ...
- 中国CIO最关心的八大问题(上)
中国CIO最关心的八大问题(上) 近期,ITValue和ValueResearch联合展开<IT决策者投资与生存状态大调查>,调查范围从关注CIO本身,延展至关注CIO所供职企业--其赖以 ...
- 【从零开始学BPM,Day3】自定义表单开发
[课程主题] 主题:5天,一起从零开始学习BPM [课程形式] 1.为期5天的短任务学习 2.每天观看一个视频,视频学习时间自由安排. [第三天课程] 1.课程概要 Step 1 软件下载:H3 BP ...
- BPM配置故事之案例3-参与者与数据自动加载
这才过了两天,阿海又来了. 阿海:公司决定改进管理方式,以后物资申请的申请人和申请部门要写具体使用人的名字和部门了. 小明:不是要让我改回去吧? 阿海:那太麻烦了,你能不能把申请人改成选择,选好人自动 ...
- Android中的多线程断点下载
首先来看一下多线程下载的原理.多线程下载就是将同一个网络上的原始文件根据线程个数分成均等份,然后每个单独的线程下载对应的一部分,然后再将下载好的文件按照原始文件的顺序"拼接"起来就 ...