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 ...
随机推荐
- 【.net 深呼吸】限制执行代码的权限
前面好几篇文章,老周都跟大伙伴们聊了跟应用程序域有关的话题,干脆咱们一聊到底吧,做学问就应该这样,有恒心. App Domain的创建新应用程序域的方法中,有一个特殊的重载: public stati ...
- Node.js:dgram模块实现UDP通信
1.什么是UDP? 这里简单介绍下,UDP,即用户数据报协议,一种面向无连接的传输层协议,提供不可靠的消息传送服务.UDP协议使用端口号为不同的应用保留其各自的数据传输通道,这一点非常重要.与TCP相 ...
- 读python源码--对象模型
学python的人都知道,python中一切皆是对象,如class生成的对象是对象,class本身也是对象,int是对象,str是对象,dict是对象....所以,我很好奇,python是怎样实现这些 ...
- java 利用ManagementFactory获取jvm,os的一些信息--转
原文地址:http://blog.csdn.net/dream_broken/article/details/49759043 想了解下某个Java项目的运行时jvm的情况,可以使用一些监控工具,比如 ...
- 在Asp.Net中操作PDF – iTextSharp - 使用表格
使用Asp.Net生成PDF最常用的元素应该是表格,表格可以帮助比如订单或者发票类型的文档更加格式化和美观.本篇文章并不会深入探讨表格,仅仅是提供一个使用iTextSharp生成表格的方法介绍 使用i ...
- 获取打开的Word文档
using Word = Microsoft.Office.Interop.Word; int _getApplicationErrorCount=0; bool _isMsOffice = true ...
- kali linux下的arp攻击
这是我第一篇博客,写的不好请谅解 ____________________________(分割线)_______________________________ 在kali linux系统下自带工具 ...
- Android事件分发机制浅谈(一)
---恢复内容开始--- 一.是什么 我们首先要了解什么是事件分发,通俗的讲就是,当一个触摸事件发生的时候,从一个窗口到一个视图,再到一个视图,直至被消费的过程. 二.做什么 在深入学习android ...
- ionic第一坑——ion-slide-box坑(ion-slide分两页的坑)
ionic.views.Slider = ionic.views.View.inherit({ initialize: function (options) { . . . function setu ...
- WINDOWS系统下MYSQL安装过程中的注意事项
1.首先MySQL的安装方式有两种:一种是MSI安装方式,很简单就像安装Windows软件一样.另外一种就是ZIP安装方式.这种相对而言比较麻烦.新手推荐MSI安装方式. 安装方式有以下两种: MSI ...