知晓和促成仓库储存格局和工作单元情势房地产项目

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应用来落到实处通用仓库储存和办事单元情势。

背景

本人记得在.NET
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基础项目搭建!)壹般是逐1执行者如下八个指令即可,笔者说1般:

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

 

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

使用MVC Scaffolding

今昔我们的备选干活1度做到,能够运用Entity
Framework来进行支付了,大家应用VS自带的MVC模板创立3个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:如若第3点感觉不清楚,那推荐阅读有关在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");
        }


    }

如今那种办法的利益是,作者的OTiguanM的数额访问代码不是分散在控制器。它被卷入在3个Repository类里面。

如何处理多个Repository库?

下边想象下如下场景,大家数据库中有多少个表,那样大家须求为各样表创立二个Reporsitory类。(好多再次工作的说,其实那小难题)

难点是关于 数据上下文(DbContext)
对象的。假使我们创制四个Repository类,是或不是每二个都独立的包蕴四个数据上下文对象?大家领略并且使用多个 数据上下文种存在难题,那我们该怎么处理每一个Repository都怀有和谐的数额上下文
对象的难题?

来缓解那么些题材呢。为何每一种Repository要具备1个数额上下文的实例呢?为何不在壹些地方成立贰个它的实例,然后在repository被实例化的时候作为参数字传送递进去吧。未来那一个新的类被取名为UnitOfWork
,此类将担负成立数量上下文实例并移交到控制器的具有repository实例。

落到实处工作单元

由此,大家在单身创制2个利用 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是越来越好的主意.

未来选择通用的贮存类,大家必要创制二个应和的干活单元类。这一个工作单元类将检查仓库储存类是还是不是早已创造,假使存在将再次来到多少个实例,不然将开创1个新的实例。

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

    }

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

主旨总结

在这篇小说中,我们精通了仓库储存形式和办事单元情势。大家也在ASP.NET
MVC应用中选用Entity
Framework实现了简约的囤积形式和做事单元形式。然后大家创制了二个通用的存款和储蓄类和办事单元类来幸免在一大堆仓库储存类中编辑重复的代码。笔者期待您在这篇文章中能有所收获

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)

译注

初稿选拔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

相关文章