博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(译文)MVC通用仓储类
阅读量:4599 次
发布时间:2019-06-09

本文共 28714 字,大约阅读时间需要 95 分钟。

Generic Repository Pattern MVC

Generic Repository Pattern MVC

原文链接:

良好的架构师任何项目的核心,开发人员一直在寻找一个牛X的架构,它能减少重复代码,分离数据访问与业务逻辑。因此,我们需要在MVC中使用EF创建一个泛型仓储类。如果不了解EF,去学习。在开始之前,我们需要了解什么是仓储模式,为什么使用仓储模式。

仓储模式和工作单元

简言之,仓储模式意味着,数据访问层与业务逻辑层之间的抽象,这是非常有利于单元测试或TDD。通过使用仓储模式,你的系统会更加松散耦合。

在开发过程中,我们通常为每个仓储或实体创建一个接口。例如,我们为Student这个实体创建一个接口约束(IStudentInterface),定义所有的CRUD操作,同时创建另一个类(StudentRepository)实现接口中所定义的所有方法。当我们在控制器中实例化仓储类的时候,我们将使用实现了对应接口的类的引用。当控制器在运行的时候,它将调用在EF基础上工作的仓储类。

当对控制器进行单元测试的时候,我们可以操作仓储类的具体数据实现,例如内存数据集。这样我们可以使用伪数据进行单元测试。

如果你想了解详细的实现,可以参照如下链接:

不利因素

每次我们都需要为实体创建仓储类,导致代码冗余

代码实现

现在我们仅仅需要一个数据访问类,介绍一些实体和执行必要的操作,例如CRUD.在学习了很多文章、理论和示例代码后,我获得了一个很好的通用的仓储模式的实现。

我的代码在很大程度上基于Huy Nguyen的博客。请参阅以下链接

我修改了很多实现代码同时添加了一些在项目中常用的代码实现。现在我能使用这个类库在任何项目。下面是文件结构:

Mayur.DAL – 通用仓储和公共方法类库

 

  • Core – 文件夹

    • GlobalCommonHelper.cs – 一个为每个项目提供大部分公共方法的抽象类
  • Repository – 文件夹

    • IRepository.cs – 通用仓储接口
    • Repository.cs – 通用仓储实现类,继承与仓储接口
    • IUnitOfWork.cs – 工作单元接口.
    • UnitOfWork.cs – 实现了EF的SaveChanges()方法。工作单元类保证我们在对数据库执行事务性的插入、更新、删除操作时,直到我们执行Savechanges()方法以后EF才会提交所做的修改。

 

Mayur.Web – MVC Web项目

 

  • Controller – 文件夹

    • HomeController.cs – 包含CRUD动作的控制器
  • Core – 文件夹

    • CommonHelper.cs – 继承于 Mayur.DAL.Core.GlobalCommonHelper.cs which 包含MVC项目中相关的公共方法。
  • Model – 文件夹

    • Student.cs – 实体类
  • Views – Folder

    • Index.chtml – 不用说了吧都
    • Create.chtml – Create new student html
    • Edit.cshtml – Update student info html
    • Delete.cshtml – Delete student info html

 

让我们简单了解下DAL中每个文件的作用:

Repository 文件夹: 在这个文件夹,包含所有的数据访问逻辑。有4个文件, 2个接口文件,两个接口的实现类

 

1. IRepository 接口

public interface IRepository : IDisposable    {        ///         ///     Gets the unit of work.        ///         /// 
The unit of work.
IUnitOfWork UnitOfWork { get; } /// /// Gets entity by key. /// ///
The type of the entity.
/// The key value. ///
TEntity GetByKey
(object keyValue) where TEntity : class; ///
/// Gets the query. /// ///
The type of the entity.
///
IQueryable
GetQuery
() where TEntity : class; ///
/// Gets the query. /// ///
The type of the entity.
///
The predicate. ///
IQueryable
GetQuery
(Expression
> predicate) where TEntity : class; ///
/// Gets all. /// ///
The type of the entity.
///
IEnumerable
GetAll
() where TEntity : class; ///
/// Gets the specified order by. /// ///
The type of the entity.
///
The type of the order by.
///
The order by. ///
Index of the page. ///
Size of the page. ///
The sort order. ///
IEnumerable
Get
(Expression
> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class; ///
/// Gets the specified criteria. /// ///
The type of the entity.
///
The type of the order by.
///
The criteria. ///
The order by. ///
Index of the page. ///
Size of the page. ///
The sort order. ///
IEnumerable
Get
(Expression
> criteria, Expression
> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class; ///
/// Gets one entity based on matching criteria /// ///
The type of the entity.
///
The criteria. ///
TEntity Single
(Expression
> criteria) where TEntity : class; ///
/// Firsts the specified predicate. /// ///
The type of the entity.
///
The predicate. ///
TEntity First
(Expression
> predicate) where TEntity : class; ///
/// Finds entities based on provided criteria. /// ///
The type of the entity.
///
The criteria. ///
IEnumerable
Find
(Expression
> criteria) where TEntity : class; ///
/// Finds one entity based on provided criteria. /// ///
The type of the entity.
///
The criteria. ///
TEntity FindOne
(Expression
> criteria) where TEntity : class; ///
/// Counts the specified entities. /// ///
The type of the entity.
///
int Count
() where TEntity : class; ///
/// Counts entities with the specified criteria. /// ///
The type of the entity.
///
The criteria. ///
int Count
(Expression
> criteria) where TEntity : class; ///
/// Adds the specified entity. /// ///
The type of the entity.
///
The entity. void Add
(TEntity entity) where TEntity : class; ///
/// Attaches the specified entity. /// ///
The type of the entity.
///
The entity. void Attach
(TEntity entity) where TEntity : class; ///
/// Updates changes of the existing entity. /// The caller must later call SaveChanges() /// on the repository explicitly to save the entity to database /// ///
The type of the entity.
///
The entity. void Update
(TEntity entity) where TEntity : class; ///
/// Deletes the specified entity. /// ///
The type of the entity.
///
The entity. void Delete
(TEntity entity) where TEntity : class; ///
/// Deletes one or many entities matching the specified criteria /// ///
The type of the entity.
///
The criteria. void Delete
(Expression
> criteria) where TEntity : class; ///
/// Deletes entities which satisfy specificatiion /// ///
The type of the entity.
///
The criteria. //void Delete
(ISpecification
criteria) where TEntity : class; }

2. Repository Class

///    ///     Generic repository Class   ///    public partial class Repository : IRepository, IDisposable   {       //Private Variables       private bool bDisposed;       private DbContext context;       private IUnitOfWork unitOfWork;       #region Contructor Logic       ///        /// Initializes a new instance of the       /// 
class. ///
public Repository() { } /// /// Initializes a new instance of the ///
class. ///
/// The context. 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
(object keyValue) where TEntity : class { EntityKey key = GetEntityKey
(keyValue); object originalItem; if (((IObjectContextAdapter)DbContext). ObjectContext.TryGetObjectByKey(key, out originalItem)) { return (TEntity)originalItem; } return default(TEntity); } public IQueryable
GetQuery
() where TEntity : class { string entityName = GetEntityName
(); return ((IObjectContextAdapter)DbContext). ObjectContext.CreateQuery
(entityName); } public IQueryable
GetQuery
(Expression
> predicate) where TEntity : class { return GetQuery
().Where(predicate); } //All Readonly Display or fetch data methods. public IEnumerable
GetAll
() where TEntity : class { return GetQuery
().AsEnumerable(); } public IEnumerable
Get
(Expression
> orderBy, int pageIndex, int pageSize, SortOrder sortOrder = SortOrder.Ascending) where TEntity : class { if (sortOrder == SortOrder.Ascending) { return GetQuery
() .OrderBy(orderBy) .Skip((pageIndex - 1) * pageSize) .Take(pageSize) .AsEnumerable(); } return GetQuery
() .OrderByDescending(orderBy) .Skip((pageIndex - 1) * pageSize) .Take(pageSize) .AsEnumerable(); } public IEnumerable
Get
(Expression
> criteria, Expression
> 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
(Expression
> criteria) where TEntity : class { return GetQuery
().Single
(criteria); } public TEntity First
(Expression
> predicate) where TEntity : class { return GetQuery
().First(predicate); } public IEnumerable
Find
(Expression
> criteria) where TEntity : class { return GetQuery
().Where(criteria); } public TEntity FindOne
(Expression
> criteria) where TEntity : class { return GetQuery
().Where(criteria).FirstOrDefault(); } public int Count
() where TEntity : class { return GetQuery
().Count(); } public int Count
(Expression
> criteria) where TEntity : class { return GetQuery
().Count(criteria); } #endregion #region Data Transactional Methods public void Add
(TEntity entity) where TEntity : class { if (entity == null) { throw new ArgumentNullException("entity"); } DbContext.Set
().Add(entity); } public void Attach
(TEntity entity) where TEntity : class { if (entity == null) { throw new ArgumentNullException("entity"); } DbContext.Set
().Attach(entity); } public void Update
(TEntity entity) where TEntity : class { string fqen = GetEntityName
(); 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 entity) where TEntity : class { if (entity == null) { throw new ArgumentNullException("entity"); } DbContext.Set
().Remove(entity); } public void Delete
(Expression
> criteria) where TEntity : class { IEnumerable
records = Find(criteria); foreach (TEntity record in records) { Delete(record); } } #endregion #region Internal Processing Private Methods private EntityKey GetEntityKey
(object keyValue) where TEntity : class { string entitySetName = GetEntityName
(); ObjectSet
objectSet = ((IObjectContextAdapter)DbContext).ObjectContext.CreateObjectSet
(); string keyPropertyName = objectSet.EntitySet.ElementType.KeyMembers[0].ToString(); var entityKey = new EntityKey (entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) }); return entityKey; } private string GetEntityName
() 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;         ///         ///     Performs application-defined tasks associated with freeing,         ///     releasing, or resetting unmanaged resources.        ///         public void Dispose()        {            Dispose(true);            GC.SuppressFinalize(this);        }         ///         ///     Disposes off the managed and unmanaged resources used.        ///         ///         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         ///         /// Take any string and encrypt it using SHA1 then        /// return the encrypted data        ///         /// input text you will enterd to encrypt it        /// 
return the encrypted text as hexadecimal string
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(); } /// /// Creates a slug url from string . /// /// ///
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; } /// /// Delete file by specified path. /// /// path of file. public void DeleteTargetFile(string path) { if (File.Exists(path)) { File.SetAttributes(path, FileAttributes.Normal); File.Delete(path); } } /// /// Sent email to target email address with attachment. /// /// Email addresses of /// one or multiple receipients semi colon (;) separated values. /// Email subject /// Email body ///
True | False
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; } /// /// Sent email to target email address with attachment. /// /// Email addresses of /// one or multiple receipients semi colon (;) separated values. /// Email subject /// Email body /// Email attachment file path ///
True | False
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; } /// /// Strips tags /// /// Text ///
Formatted text
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; } /// /// Verifies that a string is in valid e-mail format /// /// Email to verify ///
true if the string is a valid e-mail address and false if it's not
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; } /// /// Returns Allowed HTML only. /// /// Text ///
Allowed HTML
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
(null); } public virtual DbSet
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. 现在我们可以看下如何在我们的控制器中使用仓储类,看控制器中的代码:

//Constructorpublic 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
();
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
(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
(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);
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
(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
(b => b.Id == id);
113:              if (book == null)
114:              {
115:                  return HttpNotFound();
116:              }
117:              repository.Delete
(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

License

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

转载于:https://www.cnblogs.com/wwh999/p/5458036.html

你可能感兴趣的文章
渐渐磨砺--16年11月封闭总结
查看>>
[zz]GDB调试精粹及使用实例
查看>>
数据库的创建和删除
查看>>
【消息队列MQ】各类MQ比较
查看>>
最简单的三层实例【插入据
查看>>
设计模式学习笔记——Prototype原型模式
查看>>
pom.xml里有红叉报错的解决办法
查看>>
Perl last和next的用法区别
查看>>
Selenium 管理 Cookies
查看>>
ZOJ 1204 一个集合能组成多少个等式
查看>>
exceptionfunction[LeetCode]Permutations
查看>>
从int 3探索Windows应用程序调试原理
查看>>
LINUX 内核结构
查看>>
自学python记录_(3)函数
查看>>
Linux(2)_常用命令2
查看>>
自定义分页
查看>>
[转]DELPHI——调试(1)
查看>>
JS秒数转成分秒时间格式
查看>>
xp_cmdshell 命令的开启与关闭,和状态查询
查看>>
Windows10下手工强制清理删掉安装版的JRE8导致java.exe无法运行的解决办法
查看>>