原文链接: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

系列目录:

上一篇文章,讲到了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中使用仓储模式进行增删查改的更多相关文章

  1. python中关于list列表的增删查改操作

    python中list的操#python创建列表的时候,会以堆栈的形式存放数据,从右向左往堆栈中存放数据 movies=["The holy Grail","The li ...

  2. mysql中数据表记录的增删查改(2)

    select `数据表.字段1`, group_concat(`数据表.字段2`) from `数据表` group by `数据表.字段1` order by `数据表.字段1` desc; sel ...

  3. mysql中数据表记录的增删查改(1)

    数据记录的增删改查 insert into `数据表名称` (`字段名称`, ...) values ('1', ...); delete from `数据表名称` where 子句; update ...

  4. 5.在MVC中使用泛型仓储模式和工作单元来进行增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...

  5. 在MVC中使用泛型仓储模式和工作单元来进行增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...

  6. 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...

  7. 在MVC中使用泛型仓储模式和依赖注入实现增删查改

    标签: 原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository ...

  8. C# 动态生成word文档 [C#学习笔记3]关于Main(string[ ] args)中args命令行参数 实现DataTables搜索框查询结果高亮显示 二维码神器QRCoder Asp.net MVC 中 CodeFirst 开发模式实例

    C# 动态生成word文档 本文以一个简单的小例子,简述利用C#语言开发word表格相关的知识,仅供学习分享使用,如有不足之处,还请指正. 在工程中引用word的动态库 在项目中,点击项目名称右键-- ...

  9. backbonejs mvc框架的增删查改实例

    一:开发环境 coffeescript和nodejs需要先安装,没装网上自己查安装步骤. 代码编写环境及esp框架下载: esp框架下载地址:https://github.com/nonocast/e ...

随机推荐

  1. 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)

    前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...

  2. JavaScript实现DOM对象选择器

    目的: 根据传入的选择器类型选出第一个符合的DOM对象. ①可以通过id获取DOM对象,例如 $("#adom"); ②可以通过tagName获取DOM对象,例如 $(" ...

  3. Zabbix 漏洞分析

    之前看到Zabbix 出现SQL注入漏洞,自己来尝试分析. PS:我没找到3.0.3版本的 Zabbix ,暂用的是zabbix 2.2.0版本,如果有问题,请大牛指点. 0x00 Zabbix简介 ...

  4. Linux测试环境搭建的学习建议

    随着Linux应用的扩展许多朋友开始接触Linux,根据学习Windwos的经验往往有一些茫然的感觉:不知从何处开始学起.这里介绍学习Linux测试环境搭建的一些建议. 一.Linux测试环境搭建从基 ...

  5. SpringMVC初步

    SpringMVC框架介绍 1) Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面. Spring 框架提供了构建 Web 应用程序的全功 ...

  6. JavaScript中undefined与null的区别

    通常情况下, 当我们试图访问某个不存在的或者没有赋值的变量时,就会得到一个undefined值.Javascript会自动将声明是没有进行初始化的变量设为undifined. 如果一个变量根本不存在会 ...

  7. 从零开始,DIY一个jQuery(3)

    在前两章,为了方便调试,我们写了一个非常简单的 jQuery.fn.init 方法: jQuery.fn.init = function (selector, context, root) { if ...

  8. Vue.js——60分钟webpack项目模板快速入门

    概述 browserify是一个 CommonJS风格的模块管理和打包工具,上一篇我们简单地介绍了Vue.js官方基于browserify构筑的一套开发模板.webpack提供了和browserify ...

  9. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

  10. 向Java技术进军

    前两天有个朋友要我帮忙写个打印机服务,要求能应用在.net .Dephi.和java程序上面.看了下需求不难也就串口操作,所以就在周未写了个Win32的动态库,对于一个曾经写MFC程序的.net程序员 ...