原文链接: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. 【翻译】MongoDB指南/CRUD操作(三)

    [原文地址]https://docs.mongodb.com/manual/ CRUD操作(三) 主要内容: 原子性和事务(Atomicity and Transactions),读隔离.一致性和新近 ...

  2. 如何选择PHP框架?

    PHP是世界上最受欢迎的编程语言之—.最近发布的PHP7令这种服务器的编程语言比以前变得更好,更稳定了. PHP被广泛应用于重大的项目.例如Facebook就是使用PHP来维护和创建它们的内部系统的. ...

  3. HTML DOM 介绍

    本篇主要介绍DOM内容.DOM 节点.节点属性以及获取HTML元素的方法. 目录 1. 介绍 DOM:介绍DOM,以及对DOM分类和功能的说明. 2. DOM 节点:介绍DOM节点分类和节点层次. 3 ...

  4. jQuery动画-圣诞节礼物

    ▓▓▓▓▓▓ 大致介绍 下午看到了一个送圣诞礼物的小动画,正好要快到圣诞节了,就动手模仿并改进了一些小问题 原地址:花式轮播----圣诞礼物传送 思路:动画中一共有五个礼物,他们平均分布在屏幕中,设置 ...

  5. angular2系列教程(十一)路由嵌套、路由生命周期、matrix URL notation

    今天我们要讲的是ng2的路由的第二部分,包括路由嵌套.路由生命周期等知识点. 例子 例子仍然是上节课的例子:

  6. XML技术之DOM4J解析器

    由于DOM技术的解析,存在很多缺陷,比如内存溢出,解析速度慢等问题,所以就出现了DOM4J解析技术,DOM4J技术的出现大大改进了DOM解析技术的缺陷. 使用DOM4J技术解析XML文件的步骤? pu ...

  7. 算法与数据结构(十五) 归并排序(Swift 3.0版)

    上篇博客我们主要聊了堆排序的相关内容,本篇博客,我们就来聊一下归并排序的相关内容.归并排序主要用了分治法的思想,在归并排序中,将我们需要排序的数组进行拆分,将其拆分的足够小.当拆分的数组中只有一个元素 ...

  8. Windows 常用运行库下载 (DirectX、VC++、.Net Framework等)

    经常听到有朋友抱怨他的电脑运行软件或者游戏时提示缺少什么 d3dx9_xx.dll 或 msvcp71.dll.msvcr71.dll又或者是 .Net Framework 初始化之类的错误而无法正常 ...

  9. Centos6.5 配置Nginx开机自启动

    1.在/etc/init.d/目录下创建 nginx 文件,内容如下: #!/bin/sh # # nginx - this script starts and stops the nginx dae ...

  10. 分布式中使用Redis实现Session共享(二)

    上一篇介绍了一些redis的安装及使用步骤,本篇开始将介绍redis的实际应用场景,先从最常见的session开始,刚好也重新学习一遍session的实现原理.在阅读之前假设你已经会使用nginx+i ...