4.在MVC中使用倉儲模式進行增刪查改


原文鏈接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-using-the-repository-pattern-in-mvc/ 

或者:http://www.codeproject.com/Articles/644605/CRUD-Operations-Using-the-Repository-Pattern-in-MV

系列目錄:

 

 

上一篇文章,講到了MVC中基本的增刪查改,這篇文章,我會繼續說到,使用倉儲模式,進行增刪查改。

  什么是倉儲模式呢,我們先來了解一下:

 倉儲模式是為了在程序的數據訪問層和業務邏輯層之間創建一個抽象層,它是一種數據訪問模式,提供了一種更松散耦合的數據訪問方法。我們把創建數據訪問的邏輯代碼寫在單獨的類中,或者類庫中,這就是倉儲。倉儲負責和業務層進行持久化通信。在這篇文章中,我將會實現一個單一的業務模型的方法,來設計倉儲模式-----這個倉儲模式對於每一個實體都有一個倉儲類。對於Book實體,我將會創建一個倉儲接口和一個倉儲類。當我們在控制器中初始化倉儲的時候,我們使用倉儲接口,所以控制器就會接受,任何實現了這個倉儲接口的對象的引用。當控制器運行在Web服務器下的時候,它會接受一個和EF協同工作的倉儲。MVC的控制器和倉儲協同工作,去加載並持久化業務層。接着利用依賴注入,倉儲能夠被注射到控制器的構造函數中去。下面的圖表,顯示了倉儲和EF數據上下文之間的關系,在這里,MVC控制器和倉儲直接協同工作,而不是和EF。

 

那什么是EF呢,我們也來簡單的了解一下吧:

EF是一個包含在.NET Framework中的ORM框架。它可以根據數據庫表,生成業務對象和業務實體。它提供了基本的增刪查改的功能。它可以很好的管理實體之間的關系。有了EF,我們可以直接和實體模型相互協同工作,而不用和關系數據庫模型直接交互。這個抽象層,允許我們去專注於業務層的行為,還有實體之間的關系。我們使用EF數據上下文,進行查詢數據。當增刪查改中的某個操作被觸發的時候,EF就會生成必要的SQL去執行這個操作。

EF處理數據的方式?

EF允許開發者,選擇Database First【數據庫優先】,Model First【模型優先】,Code First【代碼優先】中的任何一個方式。

DataBase First【數據庫優先】

數據庫優先:是基於現有的數據庫上的,以數據為中心的設計。EF能夠基於數據庫中的表和列生成業務實體。我們數據庫的結構信息,都存儲在一個后綴名為.edmx的文件中,存儲的形式是XML。

 

 

Model First【模型優先】

在模型優先中,我們事先並不存在數據庫,並且EF為我們提供了設計器,我們可以用來設計概念上的模型。模型優先同樣使用后綴名為.edmx的文件來存儲模型和映射信息。當我們的實體模型被創建好之后,EF設計器就可以為我們生成數據庫。

 

 

 

Code First【代碼優先】

在這個代碼優先中,不管你是不是已經有數據庫了,你都可以根據表和列,來創建你自己的實體。然后使用EF【不帶后綴名為.edmx】。在代碼優先的方式中,EF不使用任何形式的配置文件(.edmx文件)來存儲數據庫,因為EF中的Mapping API使用了約定,在運行的時候,會動態為我們創建數據庫。

 

EF 6.0中已經開始支持存儲過程了:參考文章《Entity Framework 6 Code First新特性:支持存儲過程》

在這篇文章中,我會使用EF Code First在程序中開發一個數據訪問層。這背后的推動力量是使用POCO (Plain Old CLR Objects) 類。Code First使用一系列的約定,來映射POCO類,但是這可以通過Code First數據注解來改變。

 

好了,理論知識將的差不多了,現在開始將今天的正題吧:

首先看看項目結構:

我們需要在空白的資源解決方案基礎上,添加兩個類庫EF.Data、EF.Entity、還有一個空白MVC模板的EF.Web 項目;三個項目之間的引用關系,就是EF.Data需要引用EF.Entity,EF.Web項目需要引用EF.Data和EF.Entity兩個類庫。然后,EF.Data和EF.Web項目都需要引入EF框架。

這里我為了方便大家理解,也為了簡單起見,就只添加一個實體Book:

下面看看EF.Entity類庫中的Book實體代碼:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.Entity { public class Book:BaseEntity { /// <summary>
       /// 書名 /// </summary>
       public string BookTitle { get; set; } /// <summary>
       /// 價格 /// </summary>
       public decimal Price { get; set; } /// <summary>
       /// 出版商 /// </summary>
       public string PublisherName { get; set; } /// <summary>
       /// 出版時間 /// </summary>
       public DateTime PublishedDate { get; set; } } }

BaseEntity實體:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.Entity { public abstract class BaseEntity { /// <summary>
        /// 編號 /// </summary>
        public int ID { get; set; } /// <summary>
        /// 添加時間 /// </summary>
        public DateTime AddedDate { get; set; } /// <summary>
        /// 修改時間 /// </summary>
        public DateTime ModifiedDate { get; } } }

EF.Data類庫中BookMap實體:

using EF.Entity; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.ModelConfiguration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.Data { public class BookMap:EntityTypeConfiguration<Book> { public BookMap() { //配置主鍵
            this.HasKey(s => s.ID); //配置列
            this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.Property(s => s.BookTitle).HasColumnType("NVARCHAR").HasMaxLength(50).IsRequired();
this.Property(s => s.PublisherName).HasColumnType("nvarchar").HasMaxLength(50).IsRequired();
this.Property(s => s.Price).IsRequired(); this.Property(s => s.AddedDate).IsRequired(); this.Property(s => s.ModifiedDate).IsOptional(); this.Property(s => s.PublishedDate).IsRequired(); //配置表 this.ToTable("Books"); } } }

實體和映射類弄完了,開始寫EF數據上下文類:

using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.ModelConfiguration; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace EF.Data { public class EFDbContext:DbContext { public EFDbContext() : base("name=DbConnectionString") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { var typesToRegister = Assembly.GetExecutingAssembly().GetTypes() .Where(type => !String.IsNullOrEmpty(type.Namespace)) .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>)); foreach (var type in typesToRegister) { dynamic configurationInstance = Activator.CreateInstance(type); modelBuilder.Configurations.Add(configurationInstance); } } } }

連接字符串:【EF.Data和EF.Web項目都要添加】

<connectionStrings>
    <add name="DbConnectionString" connectionString="Server=.;Database=BookDB;uid=sa;Pwd=Password_1" providerName="System.Data.SqlClient"/>
  </connectionStrings>

弄完之后,我們先來開啟數據庫遷移技術吧:

在程序包管理器控制台下輸入:

Enable-Migrations

然后修改生成的Configuration類:

 

最后在程序管理器控制台輸入:

Update-Database -Verbose

 

可以看到生成的數據庫的SQL語句了。看下數據庫:

 

數據庫生成了,現在開始創建倉儲模式,來進行增刪查改吧:

using EF.Entity; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.Data { public interface IRepository { /// <summary>
       /// 獲取所有的Book /// </summary>
       /// <returns></returns>
       IEnumerable<Book> GetAllBooks(); /// <summary>
       /// 根據BookId查找Book /// </summary>
       /// <param name="bookId"></param>
       /// <returns></returns>
       Book GetBookById(int bookId); /// <summary>
       /// 添加Book /// </summary>
       /// <param name="model"></param>
       void InsertBook(Book model); /// <summary>
       /// 修改Book /// </summary>
       /// <param name="model"></param>
       void UpdateBook(Book model); /// <summary>
       /// 刪除Book /// </summary>
       /// <param name="bookId"></param>
       void DeleteBook(int bookId); /// <summary>
       /// 保存 /// </summary>
       void Save(); } }

BookRepository類:

using EF.Entity; using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.Data { public class BookRepository:IRepository { private EFDbContext db; public BookRepository() { db = new EFDbContext(); } public IEnumerable<Book> GetAllBooks() { return db.Set<Book>().ToList(); //throw new NotImplementedException();
 } public Book GetBookById(int bookId) { return db.Set<Book>().Find(bookId); //throw new NotImplementedException();
 } public void InsertBook(Book model) { db.Entry(model).State = EntityState.Added; //throw new NotImplementedException();
 } public void UpdateBook(Book model) { db.Entry(model).State = EntityState.Modified; //throw new NotImplementedException();
 } public void DeleteBook(int bookId) { Book model= db.Set<Book>().Find(bookId); db.Entry(model).State = EntityState.Deleted; //throw new NotImplementedException();
 } public void Save() { db.SaveChanges(); //throw new NotImplementedException();
 } } }

 

Book控制器代碼:

using EF.Data; using EF.Entity; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace EF.Web.Controllers { public class BookController : Controller { private IRepository _bookRepository; public BookController() { this._bookRepository = new BookRepository(); } // GET: Book
        #region Index
        public ActionResult Index() { return View(_bookRepository.GetAllBooks().ToList()); } #endregion

        #region InsertBook
        public ActionResult InsertBook() { return View(); } [HttpPost] public ActionResult InsertBook(Book model) { _bookRepository.InsertBook(model); _bookRepository.Save(); return RedirectToAction("Index"); } #endregion

        #region UpdateBook
        public ActionResult UpdateBook(int bookId) { Book model = _bookRepository.GetBookById(bookId); if (model != null) { return View(model); } else { return View(); } } [HttpPost] public ActionResult UpdateBook(Book model) { _bookRepository.UpdateBook(model); _bookRepository.Save(); return RedirectToAction("Index"); } #endregion

        #region BookDetails
        public ActionResult BookDetails(int bookId) { Book model = _bookRepository.GetBookById(bookId); if (model != null) { return View(model); } else { return View(); } } #endregion

        #region DeleteBook
        public ActionResult DeleteBook(int bookId) { Book model = _bookRepository.GetBookById(bookId); if (model != null) { return View(model); } else { return View(); } } [HttpPost] public ActionResult DeleteBook(int bookId, FormCollection form) { _bookRepository.DeleteBook(bookId); _bookRepository.Save(); return RedirectToAction("Index"); } #endregion } }

具體的視圖,根據模板生成。

修改一下默認的路由:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace EF.Web { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Book", action = "Index", id = UrlParameter.Optional } ); } } }

運行項目:

添加玩數據之后:

 

這樣就完成了使用倉儲模式,進行增刪查改的操作了。

最后看下項目完成之后的結構吧:

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM