1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository。

2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名为Repository来存放业务逻辑。

3.继续添加一个类库项目,命名为MyRepository.Domain,添加两个文件夹Models和Infrastructure。

Models来存放实体,Infrastructure来存放几个基本的类。现在目录结构已经搭建好了。

4.用NuGet确保三个项目添加了相同版本的EF,在MyRepository.DAL中引用MyRepository.Domain,在

MyRepository.Web中引用MyRepository.Domain和MyRepository.DAL。

5.在MyRepository.Domain中添加一个类BookStoreDbContext。使用EF来对数据库进行连接。

  1. public class BookStoreDbContext : DbContext
    {
    //EF从配置文件中寻找name=BookStore的数据库链接。
    //如果不指定: base("BookStore"),则寻找name=BookStoreDbContext的数据库连接
    public BookStoreDbContext()
    : base("BookStore")
    {
  2.  
  3. }
    }

下面是配置文件:

  1. <connectionStrings>
    <add name="BookStore" providerName="System.Data.SqlClient" connectionString="Data Source=.\sqlexpress;Initial Catalog=BookStore;User ID=Wangzx;Password=Wangzx01;Persist Security Info=True;"/>
    </connectionStrings>

DbContext用来与数据库建立连接完成对数据的相关操作,如果不使用Repository模式,DbContext的实例化一般放在Controller中来使用。下面开始介绍MVC3中使用Repository模式。

先把Repository模式的类图贴出来:

6.先介绍最主要的接口IRepository,该接口定义了最通用的业务逻辑操作:增、删、该。这些操作对任何一个实体的操作都是一样的。该类添加在MyRepository.Domain项目的Infrastructure文件夹中。

下面是代码:

  1. namespace MyRepository.Domain.Infrastructure
    {
    public interface IRepository<TEntity> where TEntity : class
    {
    void Insert(TEntity entity);
    void Update(TEntity entity);
    void Delete(TEntity entity);
    }
    }

这里使用泛型接口,可以用于Book,Author等不同实体的操作,只要把站位符替换掉即可。

7.下面是Repository泛型基类,它实现了IRepository接口,并使用的是泛型实现,用于对多个不同实体的操作。

具体的操作是通过DbContext来实现的,所以构造函数中要提供一个DbContext参数。该类与IRepository位于相同目录下面。

代码:

  1. namespace MyRepository.Domain.Infrastructure
    {
    public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {
    protected BookStoreDbContext dbContext;
    protected DbSet<TEntity> dbSet;
  2.  
  3. public Repository(BookStoreDbContext dbContext)
    {
    this.dbContext = dbContext;
    this.dbSet = dbContext.Set<TEntity>();
    }
    public void Insert(TEntity entity)
    {
    dbSet.Add(entity);
    }
    public void Update(TEntity entity)
    {
    dbSet.Attach(entity);
    dbContext.Entry(entity).State = EntityState.Modified;
    }
    public void Delete(TEntity entity)
    {
    if (dbContext.Entry(entity).State == EntityState.Detached)
    {
    dbSet.Attach(entity);
    }
    dbSet.Remove(entity);
    }
    }
    }

Repository类是对普遍业务操作泛型实现的地方,主要是对数据库的修改查询操作。下面的UnitOfWork 和IUnitOfWork也属于Infrastructure,这两个是用于对数据的保存。Repository和UnitOfWork都使用DbContext来对数据库进行操作,所以都有一个DbContext的字段。

  1. public interface IUnitOfWork : IDisposable
    {
    DbContext Context { get; }
    void Save();
    bool IsDisposed { get; }
    }
  1. /// <summary>
    /// 用于对数据的保存操作
    /// </summary>
    public class UnitOfWork : IUnitOfWork
    {
    private readonly BookStoreDbContext _context;
    public DbContext Context
    {
    get { return _context; }
    }
  2.  
  3. public event EventHandler Disposed;
  4.  
  5. public bool IsDisposed { get; private set; }
    public void Dispose()
    {
    Dispose(true);
    }
    public virtual void Dispose(bool disposing)
    {
    lock (this)
    {
    if (disposing && !IsDisposed)
    {
    _context.Dispose();
    var evt = Disposed;
    if (evt != null) evt(this, EventArgs.Empty);
    Disposed = null;
    IsDisposed = true;
    GC.SuppressFinalize(this);
    }
    }
    }
  6.  
  7. public UnitOfWork(BookStoreDbContext context)
    {
    _context = context;
    }
  8.  
  9. public void Save()
    {
    _context.SaveChanges();
    }
  10.  
  11. ~UnitOfWork()
    {
    Dispose(false);
    }
    }

到现在Repository模式的框架已经搭建好了,下面使用Book实体来完成一个具体的业务操作,对其他实体的操作都是下面一样的步骤。

8.1:添加实体

在MyRepository.Domain.Models文件夹下面添加一个实体类Book。

  1. [Table("Book")]
    public class Book
    {
    public int Id { get; set; }
  2.  
  3. public string ISBN { get; set; }
  4.  
  5. public string Title { get; set; }
  6.  
  7. public string Type { get; set; }
    }

8.2:修改DbContext

然后修改我们的DbContext类中添加一个DbSet属性,这样EF会在数据库中添加Book表。

  1. public class BookStoreDbContext : DbContext
    {
    //EF从配置文件中寻找name=BookStore的数据库链接。
    //如果不指定: base("BookStore"),则寻找name=BookStoreDbContext的数据库连接
    public BookStoreDbContext()
    : base("BookStore")
    {
  2.  
  3. }
  4.  
  5. public DbSet<Book> BookCollection { get; set; }
    }

8.3:添加IXXXRepository接口

在Repository类图中,只介绍了IRepoitory和Repository两个公共的类,而IXXXRepository和XXXRepository是具体使用时添加的类。下面在MyRepository.Domain文件夹下面添加一个IBookRepository,这个接口是对现有Book实体业务的扩展。可以看出该接口包含的操作种类多于IRepository接口。

  1. public interface IBookRepository : IRepository<Book>
    {
    //其他业务操作,在控制器中一般使用的是该接口
    IList<Book> GetAllBooks();
    }

8.4:实现BookRepository

在MyRepository.DAL.Repository目录下面添加一个BookRepository类。

  1. public class BookRepository : Repository<Book>, IBookRepository
    {
    //在执行子类构造函数之前,先执行基类Repository<Book>的构造函数
    public BookRepository(BookStoreDbContext dbcontext)
    : base(dbcontext)
    {
    }
  2.  
  3. public IList<Book> GetAllBooks()
    {
    var list = dbContext.BookCollection;
    return list.OrderBy(x => x.ISBN).ToList();
    }
    }

BookRepository类继承了对Book实体的所有业务操作,公共的操作在Repository<Book>中。因为BookRepository继承自Repository<Book>,而Repository<TEntity>继承并实现了IRepository<TEntity>,所以BookRepository不需要再次实现IRepository<TEntity>接口定义的方法,如果需要可以覆盖Repository<Book>的公共操作。

IBookRepository中定义了BookRepository的特有业务操作,在BookRepository必须给予实现。IBookRepository必须继承自IRepository,这样在控制器中使用IBookRepository能够包含BookRepository的所有操作。在控制器结合IOC时IBookRepository能够很好的引用BookRepository对象。

其实在企业项目中,BookRepository与MyRepository.Web中的C与V操作是不同步的。就是说不是在BookRepository完成后就立刻去写BookController,在一个控制器中可能会包含多个IXXXRepository接口类型的属性,在构造时接收XXXRepository对象。但是在这里我直接写一个简单的BookController并且不使用IOC,来简单介绍Repository模式。

9

在MyRepository.Web.Controllers中添加一个控制器MyRepository.Web.BookController

  1. public class BookController : Controller
    {
    private IBookRepository bookRepository;
    private IUnitOfWork unitOfWork;
  2.  
  3. public BookController()
    {
    BookStoreDbContext bookStoreDbContext = new BookStoreDbContext();
    bookRepository = new BookRepository(bookStoreDbContext);
    unitOfWork = new UnitOfWork(bookStoreDbContext);
    }
  4.  
  5. public ViewResult List()
    {
    IList<Book> listBook = bookRepository.GetAllBooks();
    return View(listBook);
    }
  6.  
  7. [HttpGet]
    public ViewResult Create()
    {
    return View();
    }
  8.  
  9. [HttpPost]
    public ActionResult Create(Book book)
    {
    bookRepository.Insert(book);
    unitOfWork.Save();
    return RedirectToAction("List");
    }
    }

对于View的添加,路由的设置属于MVC3的内容:http://www.bbsmvc.com/mvclearn/thread-173-1-1.html。在MVC3这本书中还提到IOC也可以结合该列子。

来源: http://www.cnblogs.com/zhongxinWang/archive/2012/02/22/2360283.html

(转)MVC中的Repository模式的更多相关文章

  1. MVC中的Repository模式

    1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository. 2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名 ...

  2. MVC架构中的Repository模式 个人理解

    关于MVC架构中的Repository模式   个人理解:Repository是一个独立的层,介于领域层与数据映射层(数据访问层)之间.它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接 ...

  3. 4.在MVC中使用仓储模式进行增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-using-the-repository-pattern-in-mvc/ 系列目录: ...

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

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

  5. 在 Laravel 5 中使用 Repository 模式实现业务逻辑和数据访问的分离

    1.概述 首先需要声明的是设计模式和使用的框架以及语言是无关的,关键是要理解设计模式背后的原则,这样才能不管你用的是什么技术,都能够在实践中实现相应的设计模式. 按照最初提出者的介绍,Reposito ...

  6. MVC单元测试,使用Repository模式、Ninject、Moq

    本篇使用Repository设计MVC项目,使用Ninject作为DI容器,借助Moq进行单元测试. 模型和EF上下文 模型很简单: public class Foo { public int Id ...

  7. Laravel 中使用 Repository 模式

    在本文中,我会向你展示如何在 Laravel 中从头开始实现 repository 设计模式.我将使用 Laravel 5.8.3 版,但 Laravel 版本不是最重要的.在开始写代码之前,你需要了 ...

  8. Asp.net MVC 中 CodeFirst 开发模式实例

    昨天写的这篇博客因为下班时间到了忘记保存了,好郁闷,得重新写一遍.实习所在公司使用的是CodeFirst开发模式,最近开始参与到公司的项目里面来了,发现这个模式特别好用,建库建表改变字段属性添加删除字 ...

  9. MVC+LINQToSQL的Repository模式之(二)数据基类

    namespace Data.TEST{    /// <summary>    /// 数据操作基类    /// </summary>    public abstract ...

随机推荐

  1. Dynamics Webservice Call with Credential

    Dynamics Webservice call with credential /// <summary> ///WebServiceHelper 的摘要说明 /// </summ ...

  2. 百度地图API示例之移动地图

    级别为6 级别为8 级别为12 代码: <!DOCTYPE html> <html> <head> <meta http-equiv="Conten ...

  3. PIC32MZ tutorial -- Hello World

    Today I implement "Hello World" on PIC32MZ EC starter kit. The application of "Hello ...

  4. 使用虚幻引擎中的C++导论(一-生成C++类)

    使用虚幻引擎中的C++导论(一) 第一,这篇是我翻译的虚幻4官网的新手编程教程,原文传送门,有的翻译不太好,但大体意思差不多,请支持我O(∩_∩)O谢谢. 第二,某些细节操作,这篇文章省略了,如果有不 ...

  5. Python自动化 【第二篇】:Python基础-列表、元组、字典

    本节内容 模块初识 .pyc简介 数据类型初识 数据运算 列表.元组操作 字符串操作 字典操作 集合操作 字符编码与转码 一.模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库, ...

  6. Oracle 查询类似 select top 的用法

    --查询前10条数据select * from MID_EHR_STAFF where rownum<10;--查询第5~10条的记录,minus(减)select * from MID_EHR ...

  7. css兼容各个浏览器的三角形图标

    css兼容各个浏览器的三角形图标 在当前流行的的网站上,我们经常会看到一些小三角形的下拉提示(微博顶部的下拉菜单),简单的方式可以使用一张图片代替,但是随着前端技术的发展,以及开发者对于前端性能的“吹 ...

  8. Ubuntu mongodb 安装和配置

    安装 MongoDB sudo apt-get install mongodb sudo apt-get install mongodb 关闭/启动 sudo service mongodb stop ...

  9. Rstudio代码的快捷键

    按tab键:有自动补全的功能 Ctrl+Enter:运行改行代码 Ctrl+1: 移动焦点到source编辑区 Ctrl+2: 移动焦点到控制台 Ctrl+enter Ctrl+L:删除该控制台的所有 ...

  10. 使用C# WinForm窗体制作经理评分项目 ——S2 2.2

    在窗口加载时初始化三个员工对象 用数组存放 这是员工类的大致字段和属性. 在FrmMain中给对象数组附初值 以上 FrmMain中用一个ListView控件展示员工信息,通过以上代码将对象数组中的内 ...