为我们透过在一个概括的MVC应用程序中贯彻仓储模式以及做事单元来替代枯燥的座谈他们(让我们经过在一个略的MVC应用程序中贯彻仓储模式以及工作单元来替枯燥的议论他们(

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; }

下一场就是以程序包管理器控制台中输入数据迁移指令来促成数据表的创导(之前的步调如果还不见面的口舌,建议事先去押下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

相关文章