数据库格局的歧异使我们为每一个应用程序编写单独的数目访问层,数据库格局的差别使我们为各种应用程序编写单独的数额访问层

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对象的实例,都足以进行数据访问。

仓储格局和行事单位方式使通过O酷路泽M举办数量访问操作更是干净清洁,把具有的数额访问二种在1个岗位,并且使程序维持可测试的力量。让我们由此在3个大致的MVC应用程序中落到实处仓储方式和办事单元来取代枯燥的议论他们(“Talk
is cheap,show me the code!)

背景

本身记得在.NET
1.1的一世,我们不得不开销多量的时刻为各类应用程序编写数据访问代码。就算代码的品质大概一致,数据库形式的歧异使大家为各个应用程序编写单独的多寡访问层。在新本子的.NET框架中,在我们的应用程序中采取orm(对象-关系映射工具)使咱们幸免像此前一样编写大批量的数码访问层的代码成为只怕

是因为orm的数目访问操作变得那么简单直接,导致数据访问逻辑和逻辑谓词(predicates)有只怕分流在全路应用程序中。例如,逐个控制器都有ObjectContext对象的实例,都可以进行多少访问。

仓储格局和办事单位格局使通过O奥德赛M进行数据访问操作更为绝望卫生,把全体的数目访问两种在三个岗位,并且使程序维持可测试的力量。让我们因而在三个大致的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中添加2个简便的 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");
        }


    }

方今那种艺术的益处是,我的O福睿斯M的数量访问代码不是散落在控制器。它被装进在五个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");
        }


    }

以往那种形式的功利是,笔者的O奇骏M的数据访问代码不是分散在控制器。它被打包在1个Repository类里面。

什么处理四个Repository库?

下边想象下如下场景,大家数据库中有多少个表,那样大家须要为逐个表创立贰个Reporsitory类。(好多再次工作的说,其实那不是题材)

题材是关于 数据上下文(DbContext)
对象的。假如大家创设多少个Repository类,是还是不是每二个都独立的盈盈多个数据上下文对象?大家通晓并且使用八个 数据上下文少禽设有难点,那我们该怎么处理各种Repository都富有和谐的数码上下文
对象的标题?

来化解这么些标题呢。为何每种Repository要持有一个数码上下文的实例呢?为啥不在一些地方成立一个它的实例,然后在repository被实例化的时候作为参数传递进去吧。今后以此新的类被取名为
UnitOfWork
,此类将肩负创造数量上下文实例并移交到控制器的持有repository实例。

哪些处理多个Repository库?

上边想象下如下场景,我们数据库中有七个表,那样大家须求为每种表创造二个Reporsitory类。(好多再次工作的说,其实那不是题材)

题材是关于 数据上下文(DbContext) 对象的。假如大家创立八个Repository类,是或不是每3个都单身的盈盈八个 数据上下文对象?大家领会并且选择七个 数据上下文 会设反常,那我们该怎么处理各个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);
        }
    }

前日我们在创建3个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
传入虚拟的测试数据来代替真实数据。同样数目访问的代码也被集中到一个地点。

心想事成工作单元

所以,我们在单身创造3个选用 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);
        }
    }

到现在我们在创立3个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类创设2个通用的储存类和
工作单元类岂不是更好,所以大家后续来促成二个通用的积存类。

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

    }

当今,大家已经在缓解方案中现实了3个通用的积存类和做事单元类

主题总计

在那篇小说中,大家了解了仓储格局和办事单元方式。大家也在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

相关文章