ASP.NET MVC 5 Repository Pattern

ASP.NET MVC 5 Repository Pattern

Vừa qua mình có làm một bài về Login & Register trong ASP.NET MVC 5. Nay mình thực hiện tạo một Repository Pattern, vậy Repository Pattern dùng đề làm gì?
Repository Pattern :  dùng để tạo một lớp trù tượng (abstraction layer ), sau đó một lớp logic kế thừa lớp trù tượng và thiết lập các chức năng cho lớp đó. Triển khai các tính chất cho lớp đó
Trong lớp trù tượng( abstraction layer ) ta khai báo các hàm cần dùng ví dụ như : (GetAll,Insert,Update,Delete). Lớp logic sẽ kế thừa từ lớp trù tượng, cài đặt các tính chất cho các hàm đã được khai báo bên lớp trù tượng
Trong bài chia sẻ này mình kết hợp với bài vừa rồi là Login & Register in ASP.NET MVC 5. Code cũng vậy chỉ sửa lại ít, Các bạn có thể xem lại bài này nhé
Đầu tiên mở file DB_Entities.cs trong thư mục Models/DB_Entities.cs và chỉnh sửa lại như sau.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace ProjectMVC5.Models
{
    public class DB_Entities: DbContext
    {
        public DB_Entities() : base("DatabaseMVC5") { }
     
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            Database.SetInitializer<DB_Entities>(null);
            modelBuilder.Entity<User>().ToTable("Users");
            base.OnModelCreating(modelBuilder);
        }
    }
}

Tạo thư mục Repositories trong Project: ProjectMVC5/Repositories. Sau đó tạo file IRepositories.css thiết lập các hàm cần phải được triển khai ở lớp logic

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ProjectMVC5.Models;
namespace ProjectMVC5.Repositories
{
    public interface IRepository<T> where T : class
    {
        IEnumerable<T> GetAll();
        T GetById(int id);
        void Insert(T obj);
        void Update(T obj);
        void Delete(int obj);
        void Save();
           
    }
}

Trong file trên ta có các hàm (GetAll,GetById,Insert,Update,Delete,Save): có nghĩa là ta cũng phải cần tạo một file kế thừa từ lớp trù tượng này, để triển khai chúng
Tạo file GenericRepository.cs trong thư mục Repositories

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ProjectMVC5.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace ProjectMVC5.Repositories
{
    public class GenericRepository<T> : IRepository<T> where T: class
    {
       
        public DB_Entities _context = null;
        public DbSet<T> table = null;
        public GenericRepository()
        {

            this._context = new DB_Entities();
            this._context.Configuration.ValidateOnSaveEnabled = false;
            this.table = _context.Set<T>();
        }
        public GenericRepository(DB_Entities _context)
        {
            this._context = _context;
            this.table = _context.Set<T>();
        }
        public IEnumerable<T> GetAll()
        {
            
            return table.ToList();
        }

        public T GetById(int id)
        {
            return table.Find(id);
        }
        public void Insert(T obj)
        {
            table.Add(obj);
        }
        public void Update(T obj)
        {
            table.Attach(obj);
            _context.Entry(obj).State = EntityState.Modified;
        }
        public void Delete(int id)
        {
            var data = table.Find(id);
            table.Remove(data);
        }
        public void Save()
        {
            _context.SaveChanges();
        }
        
    }
}

Trong đoạn code trên ta triển khai xử lý việc kết nối đến database,và triển khai các hàm đã được cài đặt trong lớp trù tượng ban đầu
Bài trước mình có viết cách kiểm tra Email người dùng, này mình sẽ kết hợp với Repositories nó sẽ khác xíu
Tạo lớp trù tượng IUserRepository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ProjectMVC5.Models;
namespace ProjectMVC5.Repositories
{
    public interface IUserRepository : IRepository<User>
    {
        User WhereEmail(string email);
        IEnumerable<User> CheckLogin(string email, string password);
    }
}

Đoạn code trên ta thiết lập hai hàm: 
WhereEmail(): dùng kiểm tra Email có tồn tại trong cơ sở dữ liệu hay không
CheckLogin(): dùng kiểm tra đăng nhập của người dùng

Bạn hãy nhớ, khi bạn đã tạo một lớp trù tượng và viết hàm trong lớp đó. 
Thì bạn cũng phải tạo một lớp kế thừa từ lớp trù tượng đó, để triển khai viết các tính năng cho lớp trù tượng đó
Tạo File UserRepository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ProjectMVC5.Models;
namespace ProjectMVC5.Repositories
{
    public class UserRepository: GenericRepository<User>,IUserRepository
    {
        public User WhereEmail(string email)
        {
           
            var data = table.FirstOrDefault(s => s.Email == email);
            return data;
        }
        public IEnumerable<User> CheckLogin(string email, string password)
        {
            var data = table.Where(s => s.Email.Equals(email) && s.Password.Equals(password)).ToList();
            return data;
        }
    }
}

Nhìn trong file UserRepository.cs mình kế thừa kế thừa từ (GenericRepository,IUserRepository) để ta có thể kế thừa các tính chất của hai lớp đó.
Vậy trong HomeController.cs ta muốn sử dụng chúng thì làm thế nào? vững nhiên là phải khai báo các lớp đó vào file,ta mới sử dụng được
Các bạn chỉ khai báo các lớp logic thôi, có nghĩa là lớp đã triển khai, các bạn nhìn trong file HomeController.cs mình đã khai báo chúng

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ProjectMVC5.Models;
using System.Security.Cryptography;
using ProjectMVC5.Repositories;
namespace ProjectMVC5.Controllers
{
    public class HomeController : Controller
    {
      
        private GenericRepository<User> repository = null;
        private UserRepository userRepository = null;
        public HomeController()
        {
            this.userRepository = new UserRepository();
            this.repository = new GenericRepository<User>();
        }
        public HomeController(GenericRepository<User> repository, UserRepository userRepository)
        {
            this.repository = repository;
            this.userRepository = userRepository;
        }
        public ActionResult Index()
        {
            if (Session["idUser"] != null)
            {
                return View();
            }
            else
            {
                return RedirectToAction("Login");
            }
        }

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

        //POST: Register
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Register(User _user)
        {
            if (ModelState.IsValid)
            {
                var check = userRepository.WhereEmail(_user.Email);
           
               if (check == null)
                {
                    _user.Password = GetMD5(_user.Password);
                    userRepository.Insert(_user);
                    userRepository.Save();
                    return RedirectToAction("Index");
                }
                else
                {
                    ViewBag.error = "Email already exists";
                    return View();
                }
                
                

            }
            return View();
            
           
        }

        public ActionResult Login()
        {
            return View();
        }


       
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Login(string email,string password)
        {
            if (ModelState.IsValid)
            {
                var f_password = GetMD5(password);
                var data = userRepository.CheckLogin(email, f_password);
                if (data.Count() > 0)
                {
                    //add session
                    Session["FullName"] = data.FirstOrDefault().FirstName +" "+ data.FirstOrDefault().LastName;
                    Session["Email"] = data.FirstOrDefault().Email;
                    Session["idUser"] = data.FirstOrDefault().idUser;
                    return RedirectToAction("Index");
                }
                else
                {
                    ViewBag.error = "Login failed";
                    return RedirectToAction("Login");
                }
                
            }
            return View();
        }
        

        //Logout
        public ActionResult Logout()
        {
            Session.Clear();//remove session
            return RedirectToAction("Login");
        }



        //create a string MD5
        public static string GetMD5(string str)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] fromData = Encoding.UTF8.GetBytes(str);
            byte[] targetData = md5.ComputeHash(fromData);
            string byte2String = null;

            for (int i = 0; i < targetData.Length; i++)
            {
                byte2String += targetData[i].ToString("x2");
               
            }
            return byte2String;
        }
       
    }
}

Ok vậy là xong! bài này hơi phức tạp, nếu mọi người thử làm vài bài demo thử, sẽ hình dung ra và hiểu đường đi nước bước của nó
Tạo Repository pattern, giúp ta có thể tái sử dụng lại code, hạn chế ảnh hưởng tới các tính năng khác trong hệ thống, bởi vì mỗi Model ta có thể tạo một Repository riêng cho chúng, sẽ không ảnh hưởng tới các model khác

Tag: ASP.NET MVC