数据库方式的差别使大家为种种应用程序编写单独的数量访问层,数据库情势的距离使大家为各种应用程序编写单独的数目访问层

MVC+EF 驾驭和促成仓储格局和工作单元方式

原文:Understanding Repository and Unit of Work Pattern and
Implementing Generic Repository in ASP.NET MVC using Entity
Framework

MVC+EF 了解和得以落成仓储形式和办事单元情势

原文:Understanding Repository and Unit of Work Pattern and
Implementing Generic Repository in ASP.NET MVC using Entity
Framework

作品介绍

在那篇文章中,大家试着来通晓Repository(下文简称仓储)和Unit of
Work(下文简称工作单元)格局。同时大家应用ASP.NET MVC和Entity Framework
搭建一个简便的web应用来完结通用仓储和做事单元方式。

小说介绍

在那篇小说中,大家试着来精晓Repository(下文简称仓储)和Unit of
Work(下文简称工作单元)情势。同时大家使用ASP.NET MVC和Entity Framework
搭建一个粗略的web应用来兑现通用仓储和做事单元方式。

背景

本身纪念在.NET
1.1的一时,我们只可以花费大批量的时刻为每个应用程序编写数据访问代码。即便代码的习性大致一样,数据库格局的异样使我们为每个应用程序编写单独的数目访问层。在新本子的.NET框架中,在大家的应用程序中行使orm(对象-关系映射工具)使大家幸免像在此此前一样编写大量的多少访问层的代码成为可能

由于orm的数额访问操作变得那么粗略间接,导致数据访问逻辑和逻辑谓词(predicates)有可能分流在漫天应用程序中。例如,每个控制器都有ObjectContext对象的实例,都可以开展多少访问。

存储情势和行事单位情势使通过ORM举办多少访问操作更为绝望卫生,把所有的数码访问三种在一个岗位,并且使程序维持可测试的力量。让大家通过在一个简短的MVC应用程序中落成仓储形式和办事单元来取代枯燥的切磋他们(“Talk
is cheap,show me the code!)

背景

我记念在.NET
1.1的一世,大家只能够成本大量的小运为每个应用程序编写数据访问代码。即使代码的性质大约千篇一律,数据库形式的反差使咱们为每个应用程序编写单独的数据访问层。在新本子的.NET框架中,在我们的应用程序中行使orm(对象-关系映射工具)使我们防止像在此从前一样编写大量的数码访问层的代码成为可能

鉴于orm的数目访问操作变得那么简单直接,导致数据访问逻辑和逻辑谓词(predicates)有可能分流在全部应用程序中。例如,每个控制器都有ObjectContext对象的实例,都得以开展数据访问。

存储格局和行事单位方式使通过ORM进行数据访问操作越发彻底卫生,把装有的数据访问两种在一个岗位,并且使程序维持可测试的力量。让我们由此在一个简短的MVC应用程序中完成仓储格局和办事单元来顶替枯燥的商量他们(“Talk
is cheap,show me the code!)

始建代码

第一利用vs创造一个MVC web应用程序,然后在Models中添加一个不难的
Books类,大家将对那些类进行数据库的CRUD操作。(原文使用的DB
First格局搭建实例,鉴于自己从起始专业接触EF就不曾认真的进展DB
First格局的读书,所以那边使用Code First方式来开突显身说法)

 [Table("Books")]
    public class Book 
    {
        [Key]
        public int Id { get; set; }

        [Column(TypeName = "varchar")]
        [MaxLength(100)]
        [Display(Name = "封面")]
        public string Cover { get; set; }
        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "书名")]
        public string BookName { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "作者")]
        public string Author { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "译名")]
        public string TranslatedName { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "译者")]
        public string Translator { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "出版社")]
        public string Publisher { get; set; }

        [Display(Name = "字数")]
        public int WordCount { get; set; }

        [Display(Name = "页数")]
        public int Pages { get; set; }

        [Column(TypeName = "varchar")]
        [MaxLength(50)]
        [Display(Name = "ISBN号")]
        public string ISBN { get; set; }

        [Column(TypeName = "float")]
        [Display(Name = "定价")]
        public double Price { get; set; }

        [Column(TypeName = "float")]
        [Display(Name = "售价")]
        public double SalePrice { get; set; }

        [Column(TypeName="date")]
        [Display(Name="出版日期")]
        public DateTime PublicationDate { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(1000)]
        [Display(Name = "内容简介")]
        [DataType(DataType.MultilineText)]
        public string Introduction { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(1000)]
        [Display(Name = "作者简介")]
        [DataType(DataType.MultilineText)]
        public string AboutTheAuthors { get; set; }

        [Column(TypeName = "varchar")]
        [MaxLength(100)]
        [Display(Name = "购买链接")]
        public string Link { get; set; }

下一场就是在程序包管理器控制奥兰多(Orlando)输入数据迁移指令来完成数据表的创始(此前的步骤如果还不会的话,提议先去看下MVC基础项目搭建!)一般是各样执行者如下五个指令即可,我说一般:

PM> Enable-migrations
PM>add-migration createBook
PM> update-database

 

可以用Vs自带的服务器资源管理器打开生成的数据库查看表音讯。

始建代码

第一利用vs创立一个MVC web应用程序,然后在Models中添加一个大致的 Books类,大家将对那几个类举办数据库的CRUD操作。(原文使用的DB
First形式搭建实例,鉴于我从初阶正式接触EF就从未当真的进展DB
First情势的上学,所以那边使用Code First形式来开突显身说法)

 [Table("Books")]
    public class Book 
    {
        [Key]
        public int Id { get; set; }

        [Column(TypeName = "varchar")]
        [MaxLength(100)]
        [Display(Name = "封面")]
        public string Cover { get; set; }
        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "书名")]
        public string BookName { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "作者")]
        public string Author { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "译名")]
        public string TranslatedName { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "译者")]
        public string Translator { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(200)]
        [Display(Name = "出版社")]
        public string Publisher { get; set; }

        [Display(Name = "字数")]
        public int WordCount { get; set; }

        [Display(Name = "页数")]
        public int Pages { get; set; }

        [Column(TypeName = "varchar")]
        [MaxLength(50)]
        [Display(Name = "ISBN号")]
        public string ISBN { get; set; }

        [Column(TypeName = "float")]
        [Display(Name = "定价")]
        public double Price { get; set; }

        [Column(TypeName = "float")]
        [Display(Name = "售价")]
        public double SalePrice { get; set; }

        [Column(TypeName="date")]
        [Display(Name="出版日期")]
        public DateTime PublicationDate { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(1000)]
        [Display(Name = "内容简介")]
        [DataType(DataType.MultilineText)]
        public string Introduction { get; set; }

        [Column(TypeName = "nvarchar")]
        [MaxLength(1000)]
        [Display(Name = "作者简介")]
        [DataType(DataType.MultilineText)]
        public string AboutTheAuthors { get; set; }

        [Column(TypeName = "varchar")]
        [MaxLength(100)]
        [Display(Name = "购买链接")]
        public string Link { get; set; }

然后就是在先后包管理器控制长沙输入数据迁移指令来促成数据表的创办(在此以前的步调假若还不会的话,提议先去看下MVC基础项目搭建!)一般是种种执行者如下两个指令即可,我说一般:

PM> Enable-migrations
PM>add-migration createBook
PM> update-database

 

可以用Vs自带的服务器资源管理器打开生成的数据库查看表音讯。

使用MVC Scaffolding

最近大家的备选干活一度完毕,可以运用Entity
Framework来进展支付了,大家应用VS自带的MVC模板成立一个Controller来形成Books
表的CRUD操作。

在缓解方案中Controllers文件夹右键,选取添加Controller,在窗口中采用“包蕴视图的MVC
x控制器(使用Entity Framework)”

图片 1

public class BooksController : Controller
    {
        private MyDbContext db = new MyDbContext();

        // GET: Books
        public ActionResult Index()
        {
            return View(db.Books.ToList());
        }

        // GET: Books/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = db.Books.Find(id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // GET: Books/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Books/Create
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                db.Books.Add(book);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(book);
        }

        // GET: Books/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = db.Books.Find(id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: Books/Edit/5
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                db.Entry(book).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(book);
        }

        // GET: Books/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = db.Books.Find(id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: Books/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Book book = db.Books.Find(id);
            db.Books.Remove(book);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }

F5起步调试,我们应当是一度足以对Books举行CRUD操作了

近日从代码和功能的角度来看这么做并没有怎么错。但那种办法有两个问题。

  1. 多少方面的代码零散分布在应用程序中(Controllers),那将是前期程序维护的惊恐不已的梦
  2. 在控制器(Controller)和动作(Action)内部创建了数码上下文(Context),那使得成效无法通过伪数据开展测试,大家不可能印证其结果,除非大家运用测试数据。(应该说是成效不足测试)

Note:要是第二点感觉不明晰,那推荐阅读有关在MVC中展开测试驱动开发(Test
Driven Development using
MVC)方面的始末。为避免离题,不再本文中进行座谈。

使用MVC Scaffolding

方今大家的备选干活早已做到,可以行使Entity
Framework来展成本付了,大家使用VS自带的MVC模板创造一个Controller来成功Books 表的CRUD操作。

在缓解方案中Controllers文件夹右键,选择添加Controller,在窗口中采取“包涵视图的MVC
x控制器(使用Entity Framework)”

图片 2

public class BooksController : Controller
    {
        private MyDbContext db = new MyDbContext();

        // GET: Books
        public ActionResult Index()
        {
            return View(db.Books.ToList());
        }

        // GET: Books/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = db.Books.Find(id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // GET: Books/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Books/Create
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                db.Books.Add(book);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(book);
        }

        // GET: Books/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = db.Books.Find(id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: Books/Edit/5
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                db.Entry(book).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(book);
        }

        // GET: Books/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = db.Books.Find(id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: Books/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Book book = db.Books.Find(id);
            db.Books.Remove(book);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }

F5开始调试,我们相应是现已足以对Books举行CRUD操作了

今昔从代码和功用的角度来看这么做并没有怎么错。但那种格局有七个问题。

  1. 数码方面的代码零散分布在应用程序中(Controllers),那将是前期程序维护的梦魇
  2. 在控制器(Controller)和动作(Action)内部创建了数量上下文(Context),这使得功效不能通过伪数据举办测试,咱们无能为力求证其结果,除非大家选用测试数据。(应该就是成效不可测试)

Note:假若第二点感觉不明晰,那推荐阅读有关在MVC中举办测试驱动开发(Test
Driven Development using
MVC)方面的情节。为严防离题,不再本文中展开切磋。

得以完毕仓储格局

当今,大家来缓解地方的题材。我们得以因此把所有包罗数据访问逻辑的代码放到一起来缓解这么些问题。所以让大家定义一个富含所有对
Books 表的多少访问逻辑的类

不过在成立这些类从前,大家也顺带考虑下第三个问题。如若大家创制一个粗略的概念了访问Books表的预约的接口然后用刚才提到的类已毕接口,大家会获得一个利益,大家得以利用另一个类伪造数据来得以完成接口。这样,就足以维持Controller是可测试的。(原文很麻烦,就是抒发那么些意思)

于是,大家先定义对 Books 进行多少访问的预定。

    public interface IRepository<T> where T:class
    {
        IEnumerable<T> GetAll(Func<T, bool> predicate = null);
        T Get(Func<T, bool> predicate);
        void Add(T entity);
        void Update(T entity);
        void Delete(T entity);
    }

上面的类富含了对 Books 表CRUD操作接口的兑现

 public class BooksRepository:IRepository<Book>
    {
        private MyDbContext dbContext = new MyDbContext();

        public IEnumerable<Book> GetAll(Func<Book, bool> predicate = null)
        {
            if(predicate!=null)
            {
                return dbContext.Books.Where(predicate);
            }
            return dbContext.Books;
        }

        public Book Get(Func<Book, bool> predicate)
        {
            return dbContext.Books.First(predicate);
        }

        public void Add(Book entity)
        {
            dbContext.Books.Add(entity);
        }

        public void Update(Book entity)
        {
            dbContext.Entry(entity).State = EntityState.Modified;
        }

        public void Delete(Book entity)
        {
            dbContext.Books.Remove(entity);
        }
        internal void SaveChanges()
        {
            dbContext.SaveChanges();
        }
    }

最近,大家创立另一个分包对 Books
表举行CRUD操作的Controller,命名为BooksRepoController

public class BooksRepoController : Controller
    {
        private BooksRepository repo = new BooksRepository();

        // GET: Books1
        public ActionResult Index()
        {
            return View(repo.GetAll().ToList());
        }

        // GET: Books1/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = repo.Get(t=>t.Id==id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // GET: Books1/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Books1/Create
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                repo.Add(book);
                repo.SaveChanges();

                return RedirectToAction("Index");
            }

            return View(book);
        }

        // GET: Books1/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = repo.Get(t => t.Id == id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: Books1/Edit/5
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                repo.Update(book);
                repo.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(book);
        }

        // GET: Books1/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = repo.Get(t => t.Id == id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: Books1/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Book book = repo.Get(t => t.Id == id);
            repo.Delete(book);

            repo.SaveChanges();
            return RedirectToAction("Index");
        }


    }

今昔这种办法的功利是,我的ORM的数量访问代码不是散落在控制器。它被卷入在一个Repository类里面。

完毕仓储形式

现行,我们来化解地方的问题。大家可以通过把所有蕴含数据访问逻辑的代码放到一起来化解这些问题。所以让大家定义一个包括所有对 Books 表的多少访问逻辑的类

可是在开立这一个类以前,大家也有意无意考虑下第七个问题。要是大家创设一个概括的定义了访问Books表的约定的接口然后用刚才提到的类已毕接口,大家会得到一个便宜,大家得以选择另一个类伪造数据来完成接口。那样,就可以保持Controller是可测试的。(原文很坚苦,就是发布那些意思)

故而,大家先定义对 Books 举办数量访问的预订。

    public interface IRepository<T> where T:class
    {
        IEnumerable<T> GetAll(Func<T, bool> predicate = null);
        T Get(Func<T, bool> predicate);
        void Add(T entity);
        void Update(T entity);
        void Delete(T entity);
    }

下边的类富含了对 Books 表CRUD操作接口的落成

 public class BooksRepository:IRepository<Book>
    {
        private MyDbContext dbContext = new MyDbContext();

        public IEnumerable<Book> GetAll(Func<Book, bool> predicate = null)
        {
            if(predicate!=null)
            {
                return dbContext.Books.Where(predicate);
            }
            return dbContext.Books;
        }

        public Book Get(Func<Book, bool> predicate)
        {
            return dbContext.Books.First(predicate);
        }

        public void Add(Book entity)
        {
            dbContext.Books.Add(entity);
        }

        public void Update(Book entity)
        {
            dbContext.Entry(entity).State = EntityState.Modified;
        }

        public void Delete(Book entity)
        {
            dbContext.Books.Remove(entity);
        }
        internal void SaveChanges()
        {
            dbContext.SaveChanges();
        }
    }

当今,我们创立另一个包蕴对 Books 表举办CRUD操作的Controller,命名为BooksRepoController

public class BooksRepoController : Controller
    {
        private BooksRepository repo = new BooksRepository();

        // GET: Books1
        public ActionResult Index()
        {
            return View(repo.GetAll().ToList());
        }

        // GET: Books1/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = repo.Get(t=>t.Id==id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // GET: Books1/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Books1/Create
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                repo.Add(book);
                repo.SaveChanges();

                return RedirectToAction("Index");
            }

            return View(book);
        }

        // GET: Books1/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = repo.Get(t => t.Id == id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: Books1/Edit/5
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                repo.Update(book);
                repo.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(book);
        }

        // GET: Books1/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = repo.Get(t => t.Id == id);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: Books1/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Book book = repo.Get(t => t.Id == id);
            repo.Delete(book);

            repo.SaveChanges();
            return RedirectToAction("Index");
        }


    }

近期这种措施的好处是,我的ORM的数码访问代码不是分散在控制器。它被装进在一个Repository类里面。

什么处理四个Repository库?

上面想象下如下场景,大家数据库中有几个表,那样我们必要为各样表创造一个Reporsitory类。(好多双重工作的说,其实那不是题材)

题材是有关 数据上下文(DbContext)
对象的。假使大家创立三个Repository类,是不是每一个都独立的隐含一个
数据上下文对象?大家清楚并且利用三个 数据上下文
会存在问题,这我们该怎么处理每个Repository都存有自己的数额上下文
对象的题材?

来缓解那个题材啊。为啥每个Repository要负有一个数据上下文的实例呢?为啥不在一些地方创设一个它的实例,然后在repository被实例化的时候作为参数传递进去吧。现在以此新的类被命名为
UnitOfWork
,此类将担负成立数量上下文实例并移交到控制器的保有repository实例。

怎么处理两个Repository库?

上面想象下如下场景,我们数据库中有六个表,那样大家需求为各样表创设一个Reporsitory类。(好多双重工作的说,其实那小意思)

题目是有关 数据上下文(DbContext) 对象的。尽管我们创制七个Repository类,是不是每一个都独立的蕴藏一个 数据上下文对象?我们知晓并且利用六个 数据上下文 会存在问题,那我们该怎么处理每个Repository都兼备和谐的数额上下文 对象的问题?

来化解这一个问题啊。为何每个Repository要负有一个数量上下文的实例呢?为何不在一些地方创设一个它的实例,然后在repository被实例化的时候作为参数传递进去吧。现在以此新的类被命名为 UnitOfWork ,此类将担负创立数量上下文实例并移交到控制器的有着repository实例。

落到实处工作单元

于是,我们在独立创造一个用到 UnitOfWork
的Repository类,数据上下文对象将从外围传递给它由此,让大家创立一个独自的囤积库将采取通过UnitOfWork类和目标上下文将被传送到此类以外。

    public class BooksRepositoryWithUow : IRepository<Book>
    {
        private MyDbContext dbContext = null;

        public BooksRepositoryWithUow(MyDbContext _dbContext)
        {
            dbContext = _dbContext;
        }
        public IEnumerable<Book> GetAll(Func<Book, bool> predicate = null)
        {
            if (predicate != null)
            {
                return dbContext.Books.Where(predicate);
            }
            return dbContext.Books;
        }
        public Book Get(Func<Book, bool> predicate)
        {
            return dbContext.Books.FirstOrDefault(predicate);
        }

        public void Add(Book entity)
        {
            dbContext.Books.Add(entity);
        }

        public void Update(Book entity)
        {
            dbContext.Entry(entity).State = EntityState.Modified;
        }

        public void Delete(Book entity)
        {
            dbContext.Books.Remove(entity);
        }

    }

方今那么些Repository类将从类的外场得到DbContext对象(每当它被创立时).

现在,假使我们创制几个仓储类,大家在存储类实例化的时候取得 ObjectContext
对象。让大家来看下 UnitOfWork 如何创立仓储类并且传递到Controller中的。

public class UnitOfWork : IDisposable
    {
        private MyDbContext dbContext = null;
        public UnitOfWork()
        {
            dbContext = new MyDbContext();
        }

        IRepository<Book> bookReporsitory = null;

        public IRepository<Book> BookRepository
        {
            get
            {
                if (bookReporsitory == null)
                {
                    bookReporsitory = new BooksRepositoryWithUow(dbContext);
                }
                return bookReporsitory;
            }
        }

        public void SaveChanges()
        {
            dbContext.SaveChanges();
        }

        private bool disposed = false;
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    dbContext.Dispose();
                }
                this.disposed = true;
            }
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }

当今我们在创造一个Controller,命名为 BooksUowController 将通过调用
工作单元类来促成 Book 表的CRUD操作

public class BooksUowController : Controller
    {
        private UnitOfWork uow = null;
        //private MyDbContext db = new MyDbContext();

        public BooksUowController() {
            uow = new UnitOfWork();
        }
        public BooksUowController(UnitOfWork _uow)
        {
            this.uow = _uow;
        }

        // GET: BookUow
        public ActionResult Index()
        {
            return View(uow.BookRepository.GetAll().ToList());
        }

        // GET: BookUow/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.BookRepository.Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // GET: BookUow/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: BookUow/Create
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                uow.BookRepository.Add(book);
                uow.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(book);
        }

        // GET: BookUow/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.BookRepository.Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: BookUow/Edit/5
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                uow.BookRepository.Update(book);
                uow.SaveChanges();

                return RedirectToAction("Index");
            }
            return View(book);
        }

        // GET: BookUow/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.BookRepository.Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: BookUow/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Book book = uow.BookRepository.Get(b => b.Id == id);
            uow.BookRepository.Delete(book);
            uow.SaveChanges();
            return RedirectToAction("Index");
        }

    }

当今,Controller通过默许的构造函数完毕了可测试能力。例如,测试项目可以为
UnitOfWork
传入虚拟的测试数据来取代真实数据。同样数目访问的代码也被集中到一个地点。

完成工作单元

为此,大家在独立创建一个应用 UnitOfWork 的Repository类,数据上下文对象将从外侧传递给它之所以,让大家创立一个单独的囤积库将运用通过UnitOfWork类和对象上下文将被传送到此类以外。

    public class BooksRepositoryWithUow : IRepository<Book>
    {
        private MyDbContext dbContext = null;

        public BooksRepositoryWithUow(MyDbContext _dbContext)
        {
            dbContext = _dbContext;
        }
        public IEnumerable<Book> GetAll(Func<Book, bool> predicate = null)
        {
            if (predicate != null)
            {
                return dbContext.Books.Where(predicate);
            }
            return dbContext.Books;
        }
        public Book Get(Func<Book, bool> predicate)
        {
            return dbContext.Books.FirstOrDefault(predicate);
        }

        public void Add(Book entity)
        {
            dbContext.Books.Add(entity);
        }

        public void Update(Book entity)
        {
            dbContext.Entry(entity).State = EntityState.Modified;
        }

        public void Delete(Book entity)
        {
            dbContext.Books.Remove(entity);
        }

    }

近来这些Repository类将从类的外面得到DbContext对象(每当它被创造时).

当今,如果咱们创造两个仓储类,大家在存储类实例化的时候得到 ObjectContext 对象。让我们来看下 UnitOfWork 怎样创造仓储类并且传递到Controller中的。

public class UnitOfWork : IDisposable
    {
        private MyDbContext dbContext = null;
        public UnitOfWork()
        {
            dbContext = new MyDbContext();
        }

        IRepository<Book> bookReporsitory = null;

        public IRepository<Book> BookRepository
        {
            get
            {
                if (bookReporsitory == null)
                {
                    bookReporsitory = new BooksRepositoryWithUow(dbContext);
                }
                return bookReporsitory;
            }
        }

        public void SaveChanges()
        {
            dbContext.SaveChanges();
        }

        private bool disposed = false;
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    dbContext.Dispose();
                }
                this.disposed = true;
            }
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }

现今大家在创立一个Controller,命名为 BooksUowController 将由此调用 工作单元类来促成 Book 表的CRUD操作

public class BooksUowController : Controller
    {
        private UnitOfWork uow = null;
        //private MyDbContext db = new MyDbContext();

        public BooksUowController() {
            uow = new UnitOfWork();
        }
        public BooksUowController(UnitOfWork _uow)
        {
            this.uow = _uow;
        }

        // GET: BookUow
        public ActionResult Index()
        {
            return View(uow.BookRepository.GetAll().ToList());
        }

        // GET: BookUow/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.BookRepository.Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // GET: BookUow/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: BookUow/Create
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                uow.BookRepository.Add(book);
                uow.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(book);
        }

        // GET: BookUow/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.BookRepository.Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: BookUow/Edit/5
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                uow.BookRepository.Update(book);
                uow.SaveChanges();

                return RedirectToAction("Index");
            }
            return View(book);
        }

        // GET: BookUow/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.BookRepository.Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: BookUow/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Book book = uow.BookRepository.Get(b => b.Id == id);
            uow.BookRepository.Delete(book);
            uow.SaveChanges();
            return RedirectToAction("Index");
        }

    }

当今,Controller通过默认的构造函数完毕了可测试能力。例如,测试项目可以为 UnitOfWork 传入虚拟的测试数据来代表真实数据。同样数目访问的代码也被集中到一个地方。

通用仓储和劳作单元

近期大家曾经创办了蕴藏类和
工作单元类。现在的题材是只要数据库包涵众多表,那样大家必要创设很多储存类,然后大家的干活单元类要求为每个仓储类创制一个拜访属性

倘使为具备的Mode类成立一个通用的囤积类和
工作单元类岂不是更好,所以大家继承来贯彻一个通用的存储类。

 public class GenericRepository<T> : IRepository<T> where T : class
    {
        private MyDbContext dbContext = null;
        IDbSet<T> _objectSet;

        public GenericRepository(MyDbContext _dbContext)
        {
            dbContext = _dbContext;
            _objectSet = dbContext.Set<T>();
        }

        public IEnumerable<T> GetAll(Expression< Func<T, bool>> predicate = null)
        {
            if (predicate != null)
            {
                return _objectSet.Where(predicate);
            }
            return _objectSet.AsEnumerable();
        }
        public T Get(Expression<Func<T, bool>> predicate)
        {
            return _objectSet.First(predicate);
        }
        public void Add(T entity)
        {
            _objectSet.Add(entity);
        }

        public void Update(T entity)
        {
            _objectSet.Attach(entity);
        }

        public void Delete(T entity)
        {
            _objectSet.Remove(entity);
        }

        public IEnumerable<T> GetAll(Func<T, bool> predicate = null)
        {
            if (predicate != null)
            {
                return _objectSet.Where(predicate);
            }
            return _objectSet.AsEnumerable();
        }

        public T Get(Func<T, bool> predicate)
        {
            return _objectSet.First(predicate);
        }
    }

UPDATE: 发现一个很有用的评价,我觉得应该置身小说中享受一下

在.NET中,对‘Where’至少有几个重写方法:

public static IQueryable Where(this IQueryable source, Expression> predicate);
public static IEnumerable Where(this IEnumerable source, Func predicate);

近来大家正在利用的是

Func<T, bool>

前日的询问将会拔取’IEnumerable’版本,在示范中,首先从数据库中取出整个表的记录,然后再履行过滤条件得到最终的结果。想要注脚这点,只要去探视生成的sql语句,它是不分包Where字句的。

若要解决那么些题材,大家须要修改’Func’ to ‘Expression Func’.

Expression<Func<T, bool>> predicate 

前天 ‘Where’方法应用的就是 ‘IQueryable’版本了。

Note: 因而看来,使用 Expression Func 比起选用 Func是更好的主意.

当今采纳通用的仓储类,我们须要成立一个遥相呼应的办事单元类。那一个工作单元类将检查仓储类是否曾经创造,借使存在将回来一个实例,否则将开创一个新的实例。

 public class GenericUnitOfWork:IDisposable
    {
        private MyDbContext dbContext=null;

        public GenericUnitOfWork()
        {
            dbContext = new MyDbContext();
        }
        public Dictionary<Type, object> repositories = new Dictionary<Type, object>();

        public IRepository<T> Repository<T>() where T : class
        {
            if (repositories.Keys.Contains(typeof(T)) == true)
            {
                return repositories[typeof(T)] as IRepository<T>;
            }
            IRepository<T> repo=new GenericRepository<T>(dbContext);
            repositories.Add(typeof(T), repo);
            return repo;
        }
        public void SaveChanges()
        {
            dbContext.SaveChanges();
        }

        private bool disposed = false;
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    dbContext.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }

下一场,大家在开创一个使用通用工作单元类 GenericUnitOfWork
的Controller,命名为GenericContactsController ,已毕对 Book
表的CRUD操作。

 public class GenericBooksController : Controller
    {
        private GenericUnitOfWork uow = null;
        //private MyDbContext db = new MyDbContext();

        public GenericBooksController()
        {
            uow = new GenericUnitOfWork();
        }

        public GenericBooksController(GenericUnitOfWork uow)
        {
            this.uow = uow;
        }

        // GET: GenericBooks
        public ActionResult Index()
        {
            return View(uow.Repository<Book>().GetAll().ToList());
        }

        // GET: GenericBooks/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.Repository<Book>().Get(b=>b.Id==id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // GET: GenericBooks/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: GenericBooks/Create
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                uow.Repository<Book>().Add(book);
                uow.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(book);
        }

        // GET: GenericBooks/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.Repository<Book>().Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: GenericBooks/Edit/5
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                uow.Repository<Book>().Update(book);
                uow.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(book);
        }

        // GET: GenericBooks/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.Repository<Book>().Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: GenericBooks/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Book book = uow.Repository<Book>().Get(b => b.Id == id);
            uow.Repository<Book>().Delete(book);
            uow.SaveChanges();
            return RedirectToAction("Index");
        }

    }

如今,大家曾经在化解方案中切实了一个通用的积存类和做事单元类

通用仓储和办事单元

方今我们早就创建了蕴藏类和 工作单元类。现在的问题是假使数据库包含众多表,这样大家必要创设很多仓储类,然后大家的劳作单元类要求为每个仓储类创立一个访问属性

假定为具有的Mode类创立一个通用的贮存类和 工作单元类岂不是更好,所以我们继续来兑现一个通用的囤积类。

 public class GenericRepository<T> : IRepository<T> where T : class
    {
        private MyDbContext dbContext = null;
        IDbSet<T> _objectSet;

        public GenericRepository(MyDbContext _dbContext)
        {
            dbContext = _dbContext;
            _objectSet = dbContext.Set<T>();
        }

        public IEnumerable<T> GetAll(Expression< Func<T, bool>> predicate = null)
        {
            if (predicate != null)
            {
                return _objectSet.Where(predicate);
            }
            return _objectSet.AsEnumerable();
        }
        public T Get(Expression<Func<T, bool>> predicate)
        {
            return _objectSet.First(predicate);
        }
        public void Add(T entity)
        {
            _objectSet.Add(entity);
        }

        public void Update(T entity)
        {
            _objectSet.Attach(entity);
        }

        public void Delete(T entity)
        {
            _objectSet.Remove(entity);
        }

        public IEnumerable<T> GetAll(Func<T, bool> predicate = null)
        {
            if (predicate != null)
            {
                return _objectSet.Where(predicate);
            }
            return _objectSet.AsEnumerable();
        }

        public T Get(Func<T, bool> predicate)
        {
            return _objectSet.First(predicate);
        }
    }

UPDATE: 发现一个很有用的评价,我认为应该置身小说中享受一下

在.NET中,对‘Where’至少有两个重写方法:

public static IQueryable Where(this IQueryable source, Expression> predicate);
public static IEnumerable Where(this IEnumerable source, Func predicate);

现在大家正在利用的是

Func<T, bool>

前几天的查询将会利用’IEnumerable’版本,在演示中,首先从数据库中取出整个表的记录,然后再进行过滤条件得到最终的结果。想要讲明这点,只要去探望生成的sql语句,它是不分包Where字句的。

若要解决那几个题材,大家须求修改’Func’ to
‘Expression Func’.

Expression<Func<T, bool>> predicate 

前几日 ‘Where’方法应用的就是 ‘IQueryable’版本了。

Note: 因而看来,使用 Expression
Func 比起利用 Func是更好的主意.

现行利用通用的贮存类,我们要求创制一个应和的做事单元类。那个工作单元类将检查仓储类是否早已创建,如若存在将再次回到一个实例,否则将成立一个新的实例。

 public class GenericUnitOfWork:IDisposable
    {
        private MyDbContext dbContext=null;

        public GenericUnitOfWork()
        {
            dbContext = new MyDbContext();
        }
        public Dictionary<Type, object> repositories = new Dictionary<Type, object>();

        public IRepository<T> Repository<T>() where T : class
        {
            if (repositories.Keys.Contains(typeof(T)) == true)
            {
                return repositories[typeof(T)] as IRepository<T>;
            }
            IRepository<T> repo=new GenericRepository<T>(dbContext);
            repositories.Add(typeof(T), repo);
            return repo;
        }
        public void SaveChanges()
        {
            dbContext.SaveChanges();
        }

        private bool disposed = false;
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    dbContext.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }

然后,我们在成立一个选取通用工作单元类 GenericUnitOfWork 的Controller,命名为GenericContactsController ,完结对 Book 表的CRUD操作。

 public class GenericBooksController : Controller
    {
        private GenericUnitOfWork uow = null;
        //private MyDbContext db = new MyDbContext();

        public GenericBooksController()
        {
            uow = new GenericUnitOfWork();
        }

        public GenericBooksController(GenericUnitOfWork uow)
        {
            this.uow = uow;
        }

        // GET: GenericBooks
        public ActionResult Index()
        {
            return View(uow.Repository<Book>().GetAll().ToList());
        }

        // GET: GenericBooks/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.Repository<Book>().Get(b=>b.Id==id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // GET: GenericBooks/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: GenericBooks/Create
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                uow.Repository<Book>().Add(book);
                uow.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(book);
        }

        // GET: GenericBooks/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.Repository<Book>().Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: GenericBooks/Edit/5
        // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
        // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,Introduction,AboutTheAuthors,Link")] Book book)
        {
            if (ModelState.IsValid)
            {
                uow.Repository<Book>().Update(book);
                uow.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(book);
        }

        // GET: GenericBooks/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Book book = uow.Repository<Book>().Get(b => b.Id == id.Value);
            if (book == null)
            {
                return HttpNotFound();
            }
            return View(book);
        }

        // POST: GenericBooks/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Book book = uow.Repository<Book>().Get(b => b.Id == id);
            uow.Repository<Book>().Delete(book);
            uow.SaveChanges();
            return RedirectToAction("Index");
        }

    }

近期,大家已经在缓解方案中现实了一个通用的囤积类和工作单元类

要领总计

在那篇小说中,大家清楚了仓储方式和行事单元形式。我们也在ASP.NET
MVC应用中使用Entity
Framework落成了简约的仓储格局和做事单元格局。然后大家创立了一个通用的储存类和劳作单元类来防止在一大堆仓储类中编辑重复的代码。我盼望你在那篇小说中能有所收获

要领统计

在这篇小说中,大家了解了储存形式和做事单元格局。大家也在ASP.NET
MVC应用中选拔Entity
Framework完结了概括的蕴藏形式和劳作单元方式。然后我们创建了一个通用的积存类和行事单元类来避免在一大堆仓储类中编辑重复的代码。我盼望您在那篇小说中能有所收获

History

07 May 2014: First version

History

07 May 2014: First version

License

This article, along with any associated source code and files, is
licensed under The Code Project Open License (CPOL)

License

This article, along with any associated source code and files, is
licensed under The Code Project Open License (CPOL)

译注

原稿选拔objectContext,使用EF图形化建模编写的言传身教代码,译者修改code
first方式

译注

初稿拔取objectContext,使用EF图形化建模编写的示范代码,译者修改code
first格局

参考

https://msdn.microsoft.com/en-us/data/jj592676.aspx

https://msdn.microsoft.com/en-us/library/system.data.entity.dbset(v=vs.113).aspx

http://stackoverflow.com/questions/8947427/differences-between-createobjectsett-sett-and-createqueryt

参考

https://msdn.microsoft.com/en-us/data/jj592676.aspx

https://msdn.microsoft.com/en-us/library/system.data.entity.dbset(v=vs.113).aspx

http://stackoverflow.com/questions/8947427/differences-between-createobjectsett-sett-and-createqueryt

转载自:http://www.cnblogs.com/wit13142/p/5432147.html