Generic Repository Pattern MVCjavascript
原文連接:http://www.codeproject.com/Articles/1095323/Generic-Repository-Pattern-MVChtml
良好的架構師任何項目的核心,開發人員一直在尋找一個牛X的架構,它能減小重複代碼,分離數據訪問與業務邏輯。所以,咱們須要在MVC中使用EF建立一個泛型倉儲類。若是不瞭解EF,去這裏學習。在開始以前,咱們須要瞭解什麼是倉儲模式,爲何使用倉儲模式。java
簡言之,倉儲模式意味着,數據訪問層與業務邏輯層之間的抽象,這是很是有利於單元測試或TDD。經過使用倉儲模式,你的系統會更加鬆散耦合。數據庫
在開發過程當中,咱們一般爲每一個倉儲或實體建立一個接口。例如,咱們爲Student這個實體建立一個接口約束(IStudentInterface),定義全部的CRUD操做,同時建立另外一個類(StudentRepository)實現接口中所定義的全部方法。當咱們在控制器中實例化倉儲類的時候,咱們將使用實現了對應接口的類的引用。當控制器在運行的時候,它將調用在EF基礎上工做的倉儲類。架構
當對控制器進行單元測試的時候,咱們能夠操做倉儲類的具體數據實現,例如內存數據集。這樣咱們能夠使用僞數據進行單元測試。mvc
若是你想了解詳細的實現,能夠參照以下連接:app
每次咱們都須要爲實體建立倉儲類,致使代碼冗餘ide
如今咱們僅僅須要一個數據訪問類,介紹一些實體和執行必要的操做,例如CRUD.在學習了不少文章、理論和示例代碼後,我得到了一個很好的通用的倉儲模式的實現。wordpress
個人代碼在很大程度上基於Huy Nguyen的博客。請參閱如下連接
•entity-framework-4-poco-repository-and-specification-pattern
•entity-framework-poco-repository-and-specification-pattern-upgraded-to-ef-5
我修改了不少實現代碼同時添加了一些在項目中經常使用的代碼實現。如今我能使用這個類庫在任何項目。下面是文件結構:
Mayur.DAL – 通用倉儲和公共方法類庫
Core – 文件夾
Repository – 文件夾
Mayur.Web – MVC Web項目
Controller – 文件夾
Core – 文件夾
Model – 文件夾
Views – Folder
讓咱們簡單瞭解下DAL中每一個文件的做用:
Repository 文件夾: 在這個文件夾,包含全部的數據訪問邏輯。有4個文件, 2個接口文件,兩個接口的實現類
1. IRepository 接口
public interface IRepository : IDisposable { /// <summary> /// Gets the unit of work. /// </summary> /// <value>The unit of work.</value> IUnitOfWork UnitOfWork { get; } /// <summary> /// Gets entity by key. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="keyValue">The key value.</param> /// <returns></returns> TEntity GetByKey<TEntity>(object keyValue) where TEntity : class; /// <summary> /// Gets the query. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <returns></returns> IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class; /// <summary> /// Gets the query. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="predicate">The predicate.</param> /// <returns></returns> IQueryable<TEntity> GetQuery<TEntity> (Expression<Func<TEntity, bool>> predicate) where TEntity : class; /// <summary> /// Gets all. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <returns></returns> IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class; /// <summary> /// Gets the specified order by. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <typeparam name="TOrderBy">The type of the order by.</typeparam> /// <param name="orderBy">The order by.</param> /// <param name="pageIndex">Index of the page.</param> /// <param name="pageSize">Size of the page.</param> /// <param name="sortOrder">The sort order.</param> /// <returns></returns> IEnumerable<TEntity> Get<TEntity, TOrderBy>(Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class; /// <summary> /// Gets the specified criteria. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <typeparam name="TOrderBy">The type of the order by.</typeparam> /// <param name="criteria">The criteria.</param> /// <param name="orderBy">The order by.</param> /// <param name="pageIndex">Index of the page.</param> /// <param name="pageSize">Size of the page.</param> /// <param name="sortOrder">The sort order.</param> /// <returns></returns> IEnumerable<TEntity> Get<TEntity, TOrderBy>(Expression<Func<TEntity, bool>> criteria, Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class; /// <summary> /// Gets one entity based on matching criteria /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="criteria">The criteria.</param> /// <returns></returns> TEntity Single<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class; /// <summary> /// Firsts the specified predicate. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="predicate">The predicate.</param> /// <returns></returns> TEntity First<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class; /// <summary> /// Finds entities based on provided criteria. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="criteria">The criteria.</param> /// <returns></returns> IEnumerable<TEntity> Find<TEntity> (Expression<Func<TEntity, bool>> criteria) where TEntity : class; /// <summary> /// Finds one entity based on provided criteria. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="criteria">The criteria.</param> /// <returns></returns> TEntity FindOne<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class; /// <summary> /// Counts the specified entities. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <returns></returns> int Count<TEntity>() where TEntity : class; /// <summary> /// Counts entities with the specified criteria. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="criteria">The criteria.</param> /// <returns></returns> int Count<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class; /// <summary> /// Adds the specified entity. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="entity">The entity.</param> void Add<TEntity>(TEntity entity) where TEntity : class; /// <summary> /// Attaches the specified entity. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="entity">The entity.</param> void Attach<TEntity>(TEntity entity) where TEntity : class; /// <summary> /// Updates changes of the existing entity. /// The caller must later call SaveChanges() /// on the repository explicitly to save the entity to database /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="entity">The entity.</param> void Update<TEntity>(TEntity entity) where TEntity : class; /// <summary> /// Deletes the specified entity. /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="entity">The entity.</param> void Delete<TEntity>(TEntity entity) where TEntity : class; /// <summary> /// Deletes one or many entities matching the specified criteria /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="criteria">The criteria.</param> void Delete<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class; /// <summary> /// Deletes entities which satisfy specificatiion /// </summary> /// <typeparam name="TEntity">The type of the entity.</typeparam> /// <param name="criteria">The criteria.</param> //void Delete<TEntity> (ISpecification<TEntity> criteria) where TEntity : class; }
2. Repository Class
/// <summary> /// Generic repository Class /// </summary> public partial class Repository : IRepository, IDisposable { //Private Variables private bool bDisposed; private DbContext context; private IUnitOfWork unitOfWork; #region Contructor Logic /// <summary> /// Initializes a new instance of the /// <see cref="Repository<TEntity>"/> class. /// </summary> public Repository() { } /// <summary> /// Initializes a new instance of the /// <see cref="Repository<TEntity>" /> class. /// </summary> /// <param name="context">The context.</param> public Repository(DbContext contextObj) { if (contextObj == null) throw new ArgumentNullException("context"); this.context = contextObj; } public Repository(ObjectContext contextObj) { if (contextObj == null) throw new ArgumentNullException("context"); context = new DbContext(contextObj, true); } public void Dispose() { Close(); } #endregion #region Properties //DbContext Property protected DbContext DbContext { get { if (context == null) throw new ArgumentNullException("context"); return context; } } //Unit of Work Property public IUnitOfWork UnitOfWork { get { if (unitOfWork == null) { unitOfWork = new UnitOfWork(DbContext); } return unitOfWork; } } #endregion #region Data Display Methods //Helper Method tp create Query [IQuerable] public TEntity GetByKey<TEntity>(object keyValue) where TEntity : class { EntityKey key = GetEntityKey<TEntity>(keyValue); object originalItem; if (((IObjectContextAdapter)DbContext). ObjectContext.TryGetObjectByKey(key, out originalItem)) { return (TEntity)originalItem; } return default(TEntity); } public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class { string entityName = GetEntityName<TEntity>(); return ((IObjectContextAdapter)DbContext). ObjectContext.CreateQuery<TEntity>(entityName); } public IQueryable<TEntity> GetQuery<TEntity> (Expression<Func<TEntity, bool>> predicate) where TEntity : class { return GetQuery<TEntity>().Where(predicate); } //All Readonly Display or fetch data methods. public IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class { return GetQuery<TEntity>().AsEnumerable(); } public IEnumerable<TEntity> Get<TEntity, TOrderBy> (Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class { if (sortOrder == SortOrder.Ascending) { return GetQuery<TEntity>() .OrderBy(orderBy) .Skip((pageIndex - 1) * pageSize) .Take(pageSize) .AsEnumerable(); } return GetQuery<TEntity>() .OrderByDescending(orderBy) .Skip((pageIndex - 1) * pageSize) .Take(pageSize) .AsEnumerable(); } public IEnumerable<TEntity> Get<TEntity, TOrderBy>(Expression<Func<TEntity, bool>> criteria, Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class { if (sortOrder == SortOrder.Ascending) { return GetQuery(criteria). OrderBy(orderBy). Skip((pageIndex - 1) * pageSize). Take(pageSize) .AsEnumerable(); } return GetQuery(criteria) .OrderByDescending(orderBy) .Skip((pageIndex - 1) * pageSize) .Take(pageSize) .AsEnumerable(); } public TEntity Single<TEntity> (Expression<Func<TEntity, bool>> criteria) where TEntity : class { return GetQuery<TEntity>().Single<TEntity>(criteria); } public TEntity First<TEntity> (Expression<Func<TEntity, bool>> predicate) where TEntity : class { return GetQuery<TEntity>().First(predicate); } public IEnumerable<TEntity> Find<TEntity> (Expression<Func<TEntity, bool>> criteria) where TEntity : class { return GetQuery<TEntity>().Where(criteria); } public TEntity FindOne<TEntity> (Expression<Func<TEntity, bool>> criteria) where TEntity : class { return GetQuery<TEntity>().Where(criteria).FirstOrDefault(); } public int Count<TEntity>() where TEntity : class { return GetQuery<TEntity>().Count(); } public int Count<TEntity> (Expression<Func<TEntity, bool>> criteria) where TEntity : class { return GetQuery<TEntity>().Count(criteria); } #endregion #region Data Transactional Methods public void Add<TEntity>(TEntity entity) where TEntity : class { if (entity == null) { throw new ArgumentNullException("entity"); } DbContext.Set<TEntity>().Add(entity); } public void Attach<TEntity>(TEntity entity) where TEntity : class { if (entity == null) { throw new ArgumentNullException("entity"); } DbContext.Set<TEntity>().Attach(entity); } public void Update<TEntity>(TEntity entity) where TEntity : class { string fqen = GetEntityName<TEntity>(); object originalItem; EntityKey key = ((IObjectContextAdapter)DbContext).ObjectContext.CreateEntityKey(fqen, entity); if (((IObjectContextAdapter)DbContext).ObjectContext.TryGetObjectByKey (key, out originalItem)) { ((IObjectContextAdapter)DbContext).ObjectContext.ApplyCurrentValues (key.EntitySetName, entity); } } public void Delete<TEntity>(TEntity entity) where TEntity : class { if (entity == null) { throw new ArgumentNullException("entity"); } DbContext.Set<TEntity>().Remove(entity); } public void Delete<TEntity>(Expression<Func<TEntity, bool>> criteria) where TEntity : class { IEnumerable<TEntity> records = Find(criteria); foreach (TEntity record in records) { Delete(record); } } #endregion #region Internal Processing Private Methods private EntityKey GetEntityKey<TEntity>(object keyValue) where TEntity : class { string entitySetName = GetEntityName<TEntity>(); ObjectSet<TEntity> objectSet = ((IObjectContextAdapter)DbContext).ObjectContext.CreateObjectSet<TEntity>(); string keyPropertyName = objectSet.EntitySet.ElementType.KeyMembers[0].ToString(); var entityKey = new EntityKey (entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) }); return entityKey; } private string GetEntityName<TEntity>() where TEntity : class { // Thanks to Kamyar Paykhan - // http://huyrua.wordpress.com/2011/04/13/ // entity-framework-4-poco-repository-and-specification-pattern-upgraded-to-ef-4-1/ // #comment-688 string entitySetName = ((IObjectContextAdapter)DbContext).ObjectContext .MetadataWorkspace .GetEntityContainer(((IObjectContextAdapter)DbContext). ObjectContext.DefaultContainerName, DataSpace.CSpace) .BaseEntitySets.Where(bes => bes.ElementType.Name == typeof(TEntity).Name).First().Name; return string.Format("{0}.{1}", ((IObjectContextAdapter)DbContext).ObjectContext.DefaultContainerName, entitySetName); } private string RemoveAccent(string txt) { byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(txt); return System.Text.Encoding.ASCII.GetString(bytes); } private bool IsValidTag(string tag, string tags) { string[] allowedTags = tags.Split(','); if (tag.IndexOf("javascript") >= 0) return false; if (tag.IndexOf("vbscript") >= 0) return false; if (tag.IndexOf("onclick") >= 0) return false; var endchars = new char[] { ' ', '>', '/', '\t' }; int pos = tag.IndexOfAny(endchars, 1); if (pos > 0) tag = tag.Substring(0, pos); if (tag[0] == '/') tag = tag.Substring(1); foreach (string aTag in allowedTags) { if (tag == aTag) return true; } return false; } #endregion #region Disposing Methods protected void Dispose(bool bDisposing) { if (!bDisposed) { if (bDisposing) { if (null != context) { context.Dispose(); } } bDisposed = true; } } public void Close() { Dispose(true); GC.SuppressFinalize(this); } #endregion } }
3. IUnitOfWork Interface
public interface IUnitOfWork : IDisposable { void SaveChanges(); }
4. UnitOfWork Class
internal class UnitOfWork : IUnitOfWork { private readonly DbContext _dbContext; public UnitOfWork(DbContext context) { _dbContext = context; } public void SaveChanges() { ((IObjectContextAdapter)_dbContext).ObjectContext.SaveChanges(); } #region Implementation of IDisposable private bool _disposed; /// <summary> /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Disposes off the managed and unmanaged resources used. /// </summary> /// <param name="disposing"></param> private void Dispose(bool disposing) { if (!disposing) return; if (_disposed) return; _disposed = true; } #endregion }
在Mayur.DAL.Core文件夾中,還有一個抽象類,包含了一些項目中經常使用到的公共方法,若是你也有一些新的方法函數是咱們在項目中須要的,請在評論中提出建議(原文這麼說的,在我這評論我也不介意)。
5. Mayur.DAL.Core.GlobalCommonHelper.cs Class
abstract public class GlobalCommonHelper { #region General Methods /// <summary> /// Take any string and encrypt it using SHA1 then /// return the encrypted data /// </summary> /// <param name="data">input text you will enterd to encrypt it</param> /// <returns>return the encrypted text as hexadecimal string</returns> public string GetSHA1HashData(string data) { //create new instance of md5 SHA1 sha1 = SHA1.Create(); //convert the input text to array of bytes byte[] hashData = sha1.ComputeHash(Encoding.Default.GetBytes(data)); //create new instance of StringBuilder to save hashed data StringBuilder returnValue = new StringBuilder(); //loop for each byte and add it to StringBuilder for (int i = 0; i < hashData.Length; i++) { returnValue.Append(hashData[i].ToString()); } // return hexadecimal string return returnValue.ToString(); } /// <summary> /// Creates a slug url from string . /// </summary> /// <param name="phrase"></param> /// <returns></returns> public string GetSlugURLFromString(string phrase) { string str = RemoveAccent(phrase).ToLower(); // invalid chars str = Regex.Replace(str, @"[^a-z0-9\s-]", ""); // convert multiple spaces into one space str = Regex.Replace(str, @"\s+", " ").Trim(); // cut and trim str = str.Substring(0, str.Length <= 45 ? str.Length : 45).Trim(); str = Regex.Replace(str, @"\s", "-"); // hyphens return str; } /// <summary> /// Delete file by specified path. /// </summary> /// <param name="path">path of file.</param> public void DeleteTargetFile(string path) { if (File.Exists(path)) { File.SetAttributes(path, FileAttributes.Normal); File.Delete(path); } } /// <summary> /// Sent email to target email address with attachment. /// </summary> /// <param name="toEmail">Email addresses of /// one or multiple receipients semi colon (;) separated values.</param> /// <param name="subject">Email subject</param> /// <param name="body">Email body</param> /// <returns>True | False</returns> public bool SendEmailToTarget(string toEmail, string subject, string body) { bool success = false; try { SmtpClient SmtpServer = new SmtpClient(); MailMessage mail = new MailMessage(); SmtpServer.Credentials = new NetworkCredential( Convert.ToString(ConfigurationManager.AppSettings["fromEmail"]), Convert.ToString(ConfigurationManager.AppSettings["fromPassword"])); SmtpServer.Host = Convert.ToString (ConfigurationManager.AppSettings["hostName"]); SmtpServer.Port = Convert.ToInt32 (ConfigurationManager.AppSettings["portNumber"]); if (Convert.ToBoolean (ConfigurationManager.AppSettings["isEnableSSL"]) == true) SmtpServer.EnableSsl = true; mail.From = new MailAddress(Convert.ToString (ConfigurationManager.AppSettings["senderName"])); string[] multiEmails = toEmail.Split(';'); foreach (string email in multiEmails) { mail.To.Add(email); } mail.Subject = subject; mail.IsBodyHtml = true; mail.Body = body; SmtpServer.Send(mail); mail.Dispose(); success = true; } catch (Exception) { success = false; } return success; } /// <summary> /// Sent email to target email address with attachment. /// </summary> /// <param name="toEmail">Email addresses of /// one or multiple receipients semi colon (;) separated values.</param> /// <param name="subject">Email subject</param> /// <param name="body">Email body</param> /// <param name="body">Email attachment file path</param> /// <returns>True | False</returns> public bool SendEmailToTarget(string toEmail, string subject, string body, string attachmentPath) { bool success = false; try { SmtpClient SmtpServer = new SmtpClient(); MailMessage mail = new MailMessage(); SmtpServer.Credentials = new NetworkCredential( Convert.ToString(ConfigurationManager.AppSettings["fromEmail"]), Convert.ToString(ConfigurationManager.AppSettings["fromPassword"])); SmtpServer.Host = Convert.ToString (ConfigurationManager.AppSettings["hostName"]); SmtpServer.Port = Convert.ToInt32 (ConfigurationManager.AppSettings["portNumber"]); if (Convert.ToBoolean(ConfigurationManager.AppSettings["isEnableSSL"]) == true) SmtpServer.EnableSsl = true; mail.From = new MailAddress(Convert.ToString (ConfigurationManager.AppSettings["senderName"])); string[] multiEmails = toEmail.Split(';'); foreach (string email in multiEmails) { mail.To.Add(email); } Attachment attachment; attachment = new System.Net.Mail.Attachment(attachmentPath); mail.Attachments.Add(attachment); mail.Subject = subject; mail.IsBodyHtml = true; mail.Body = body; SmtpServer.Send(mail); mail.Dispose(); success = true; } catch (Exception) { success = false; } return success; } /// <summary> /// Strips tags /// </summary> /// <param name="text">Text</param> /// <returns>Formatted text</returns> public string RemoveHtmlFromString(string text) { if (String.IsNullOrEmpty(text)) return string.Empty; text = Regex.Replace(text, @"(>)(\r|\n)*(<)", "><"); text = Regex.Replace(text, "(<[^>]*>)([^<]*)", "$2"); text = Regex.Replace(text, "(&#x?[0-9]{2,4};|"|&| |<|>|€|©|®|‰|‡|†|‹| ›|„|」|「|‚|’|‘|—| –||||| | | |˜| ˆ|Ÿ|š|Š)", "@"); return text; } /// <summary> /// Verifies that a string is in valid e-mail format /// </summary> /// <param name="email">Email to verify</param> /// <returns>true if the string is a valid e-mail address and false if it's not</returns> public bool IsValidEmail(string email) { if (String.IsNullOrEmpty(email)) return false; email = email.Trim(); var result = Regex.IsMatch(email, "^(?:[\\w\\!\\#\\$\\%\\&\\ '\\*\\+\\-\\/\\=\\?\\^\\`\\{\\|\\}\\~]+\\.)*[\\w\\!\\#\\$\\%\\&\\ '\\*\\+\\-\\/\\=\\?\\^\\`\\{\\|\\}\\~]+@(?:(?:(?:[a-zA-Z0-9] (?:[a-zA-Z0-9\\-](?!\\.)){0,61}[a-zA-Z0-9]?\\.)+[a-zA-Z0-9] (?:[a-zA-Z0-9\\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\\[(?:(?:[01]?\\d{1,2}|2[0-4] \\d|25[0-5])\\.){3}(?:[01]?\\d{1,2}|2[0-4]\\d|25[0-5])\\]))$", RegexOptions.IgnoreCase); return result; } /// <summary> /// Returns Allowed HTML only. /// </summary> /// <param name="text">Text</param> /// <returns>Allowed HTML</returns> public string EnsureOnlyAllowedHtml(string text) { if (String.IsNullOrEmpty(text)) return string.Empty; const string allowedTags = "br,hr,b,i,u,a,div,ol,ul,li,blockquote,img,span,p,em," + "strong,font,pre,h1,h2,h3,h4,h5,h6,address,cite"; var m = Regex.Matches(text, "<.*?>", RegexOptions.IgnoreCase); for (int i = m.Count - 1; i >= 0; i--) { string tag = text.Substring(m[i].Index + 1, m[i].Length - 1).Trim().ToLower(); if (!IsValidTag(tag, allowedTags)) { text = text.Remove(m[i].Index, m[i].Length); } } return text; } #endregion #region Internal Processing Private Methods private string RemoveAccent(string txt) { byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(txt); return System.Text.Encoding.ASCII.GetString(bytes); } private bool IsValidTag(string tag, string tags) { string[] allowedTags = tags.Split(','); if (tag.IndexOf("javascript") >= 0) return false; if (tag.IndexOf("vbscript") >= 0) return false; if (tag.IndexOf("onclick") >= 0) return false; var endchars = new char[] { ' ', '>', '/', '\t' }; int pos = tag.IndexOfAny(endchars, 1); if (pos > 0) tag = tag.Substring(0, pos); if (tag[0] == '/') tag = tag.Substring(1); foreach (string aTag in allowedTags) { if (tag == aTag) return true; } return false; } #endregion }
如今通用倉儲已經具有了公共的方法,如今來看下咱們怎麼在控制器中使用它。假設咱們有一個Student實體,包含studentID, name, rollNo 等列,下面是控制器中的代碼
1. 在繼續以前,咱們須要先完善數據上下文信息,以生成數據庫和數據表 ,以下:
public partial class MyFirstDbContext : DbContext { public MyFirstDbContext() : base("name=MyFirstDbContext") { Database.SetInitializer<MyFirstDbContext>(null); } public virtual DbSet<Students> Students { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { } }
2. 我在數據訪問層建立了一個抽象的包含了每一個項目中都要使用的公共方法的類。由於是一個抽象類,這意味着咱們爲它建立實例。因此咱們須要建立一個新的類在Web項目中,這個類繼承於GlobalCommonHelper類,命名爲CommonHelper,咱們能夠在這個類中實現一些項目獨有的公共方法。
public class CommonHelper : GlobalCommonHelper { public int PageSize = 25; //Some common functions. Only Project-specific. }
3. 如今咱們能夠看下如何在咱們的控制器中使用倉儲類,看控制器中的代碼:
//Constructor public HomeController() { IRepository repository = new Repository(new MyFirstDbContex); CommonHelper helper = new CommonHelper(); }
1: public class BooksController : Controller
2: {
3: private IRepository repository;
4: private CommonHelper helper;
5:
6: public BooksController()
7: {
8: repository=new Repository(new MyFirstDbContext());
9: helper=new CommonHelper();
10: }
11:
12: // GET: Books
13: public ActionResult Index()
14: {
15: var list = repository.GetAll<Book>();
16: return View(list);
17: }
18:
19: // GET: Books/Details/5
20: public ActionResult Details(int id=0)
21: {
22: if (id == 0)
23: {
24: return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
25: }
26:
27: Book book = repository.FindOne<Book>(b => b.Id == id);
28: if (book == null)
29: {
30: return HttpNotFound();
31: }
32: return View(book);
33: }
34:
35: // GET: Books/Create
36: public ActionResult Create()
37: {
38: return View();
39: }
40:
41: // POST: Books/Create
42: // 爲了防止「過多發佈」攻擊,請啓用要綁定到的特定屬性,有關
43: // 詳細信息,請參閱 http://go.microsoft.com/fwlink/?LinkId=317598。
44: [HttpPost]
45: [ValidateAntiForgeryToken]
46: public ActionResult Create([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,SalePrice,PublicationDate,Introduction,AboutTheAuthors,Link")] Book book)
47: {
48: if (ModelState.IsValid)
49: {
50: repository.Add(book);
51: repository.UnitOfWork.SaveChanges();
52:
53: return RedirectToAction("Index");
54: }
55:
56: return View(book);
57: }
58:
59: // GET: Books/Edit/5
60: public ActionResult Edit(int id=0)
61: {
62: if (id == 0)
63: {
64: return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
65: }
66: Book book = repository.FindOne<Book>(x => x.Id == id);
67: if (book == null)
68: {
69: return HttpNotFound();
70: }
71: return View(book);
72: }
73:
74: // POST: Books/Edit/5
75: // 爲了防止「過多發佈」攻擊,請啓用要綁定到的特定屬性,有關
76: // 詳細信息,請參閱 http://go.microsoft.com/fwlink/?LinkId=317598。
77: [HttpPost]
78: [ValidateAntiForgeryToken]
79: public ActionResult Edit([Bind(Include = "Id,Cover,BookName,Author,TranslatedName,Translator,Publisher,WordCount,Pages,ISBN,Price,SalePrice,PublicationDate,Introduction,AboutTheAuthors,Link")] Book book)
80: {
81: if (ModelState.IsValid)
82: {
83: repository.Update<Book>(book);
84: repository.UnitOfWork.SaveChanges();
85: //db.Entry(book).State = EntityState.Modified;
86: //db.SaveChanges();
87: return RedirectToAction("Index");
88: }
89: return View(book);
90: }
91:
92: // GET: Books/Delete/5
93: public ActionResult Delete(int id=0)
94: {
95: if (id == 0)
96: {
97: return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
98: }
99: Book book = repository.FindOne<Book>(b => b.Id == id);
100: if (book == null)
101: {
102: return HttpNotFound();
103: }
104: return View(book);
105: }
106:
107: // POST: Books/Delete/5
108: [HttpPost, ActionName("Delete")]
109: [ValidateAntiForgeryToken]
110: public ActionResult DeleteConfirmed(int id)
111: {
112: Book book = repository.FindOne<Book>(b => b.Id == id);
113: if (book == null)
114: {
115: return HttpNotFound();
116: }
117: repository.Delete<Book>(book);
118: repository.UnitOfWork.SaveChanges();
119: //db.Books.Remove(book);
120: //db.SaveChanges();
121: return RedirectToAction("Index");
122: }
123:
124: }
我須要更多來自你的建議和改進,請提給我吧。(原做)
正好在學習倉儲模式和工做單元,想整理一個通用的倉儲類,做者的作參考。
英語很差有些翻譯很生硬,還有的直接表意,省掉了做者一些話(他們寫文章都很認真,像教小學生同樣敦敦教誨)
•31/05/2015: Article published
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
轉載自:http://www.cnblogs.com/wit13142/p/5435368.html