详解ASP.NET MVC对表进行通用的增删改
创始人
2024-06-11 10:40:51
0

作者的写下此文的背景是一些项目本身规模不大的情况下,也有其他网友担心性能方面的问题。在这里我们先看一下ASP.NET MVC对表是如何进行通用的增删改操作的。

预备知识:

1、了解反射技术

2、了解C#3.0中扩展方法,分布类,Linq to object,Linq to sql

3、了解ASP.NET MVC

在项目中每添加一个表往往都要添加一套增删改代码,而且这些代码很多情况下都很相似,这里我们给出一个通用的解决方案供大家参考。

一、准备工作:

这里我们先要在数据库中添加两个表News和User如下图:然后拖到dbml中生成实体类。

数据库中添加两个表News和User

这里我们先准备一个接口:ICommonTable

  1. Code  
  2. public  interface ICommonTable  
  3. {  
  4. int id { getset; }  

然后让News和User实体都继承于此接口

  1. Code  
  2. public partial class News : ICommonTable  
  3. {  
  4. }  
  5. public partial class User : ICommonTable  
  6. {  

二、通用删除操作

分别添加NewsList.aspx和UserList.aspx两个view,添加方式参见ASP.NET MVC实践系列2-简单应用

在这两个View中加入删除链接:

  1. <%= Html.ActionLink("删除", "Delete", new { key = item.id, partialName="News" })%> 
  2. 和  
  3. <%= Html.ActionLink("删除", "Delete", new { key = item.id, partialName="User" })%> 

然后添加一个Controller:

  1. public ActionResult Delete(string partialName, int? key)  
  2. {  
  3. RepositoryBase repositoryBase = new RepositoryBase(partialName);  
  4. repositoryBase.Delete(key ?? 0);  
  5. return RedirectToAction(partialName + "List");//返回到list  

接下来我们介绍一下RepositoryBase :

  1. public class RepositoryBase  
  2. {  
  3. public Type EntityType { getprivate set; }  
  4. public RepositoryBase(string entityType)  
  5. {  
  6. Type type = GetBllTypeByName(entityType);  
  7.  
  8. EntityType = type;  
  9. }  
  10. public ICommonTable CreateNew()  
  11. {  
  12. return (ICommonTable)Activator.CreateInstance(EntityType);  
  13. }  
  14. ///   
  15. /// 通过字符串获得其Type  
  16. /// 
  17.  
  18. ///   
  19. ///   
  20. private static Type GetBllTypeByName(string typeName)  
  21. {  
  22. Type type = null;  
  23. var ass = AppDomain.CurrentDomain.GetAssemblies()  
  24. .Where(p => p.FullName.Contains("CommonCEDemo"));  
  25. foreach (var a in ass)  
  26. {  
  27. type = a.GetTypes().Where(p => p.Name == typeName).FirstOrDefault();  
  28. if (type != null)  
  29. break;  
  30. }  
  31.  
  32. if (type == null)  
  33. {  
  34. throw new Exception("类型未定义:" + typeName);  
  35. }  
  36. return type;  
  37. }  
  38. public RepositoryBase(Type entityType)  
  39. {  
  40. EntityType = entityType;  
  41. }  
  42. public ICommonTable Get(int id)  
  43. {  
  44. DBDataContext db = Context.GetContext();  
  45. return db.GetTable(EntityType).Cast().FirstOrDefault(p => p.id == id);  
  46. }  
  47. public void Delete(int id)  
  48. {  
  49. ICommonTable bllTable = Get(id);  
  50. Context.GetContext().GetTable(EntityType).DeleteOnSubmit(bllTable);  
  51. Context.GetContext().SubmitChanges();  
  52. }  

这里边重点要理解的就是GetBllTypeByName方法。有了这个方法我们就可以动态的通过名字获得相应的Type了。这里还有个问题就是DataContext是从何而来的,我们这里为了简单起见全程声明了一个DataContext没有考虑多线程的情况

  1. public class Context  
  2. {  
  3. static DBDataContext context;  
  4. static Context()  
  5. {  
  6. if (context==null)  
  7. {  
  8. context = new DBDataContext();  
  9. }  
  10. }  
  11. public static DBDataContext GetContext()  
  12. {  
  13. return context;  
  14. }  

有个这些当我们想要对一个表进行删除是只要添加相应的链接就可以了(如<%= Html.ActionLink("删除", "Delete", new { key = item.id, partialName="News" })%>)

三、通用增加、修改

首先添加一个CreateEditView.aspx视图

  1.  ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 
  2. <%Html.RenderPartial(ViewData["PartialName"].ToString()); %> 
  3.  

然后添加两个Partial视图News.ascx和User.ascx,这两个视图是分别基于News和User类的强类型视图,具体内容参加源码。
接下来我们添加相应的Controller

  1. public ActionResult CreateEditView(string partialName, int? key)  
  2. {  
  3. ViewData["PartialName"] = partialName;  
  4. RepositoryBase repositoryBase = new RepositoryBase(partialName);  
  5. ICommonTable table;  
  6. if (key == null)  
  7. {  
  8. table = repositoryBase.CreateNew();  
  9. }  
  10. else 
  11. {  
  12. table = repositoryBase.Get(key ?? 0);  
  13. }  
  14.  
  15. return View("CreateEditView", table);  
  16. }  
  17. [AcceptVerbs(HttpVerbs.Post)]  
  18. public ActionResult CreateEditView(string partialName, int? key, FormCollection formCollection)  
  19. {  
  20. RepositoryBase repositoryBase = new RepositoryBase(partialName);  
  21. ICommonTable bllTable;  
  22. if (key == null)  
  23. {  
  24. bllTable = repositoryBase.CreateNew();  
  25. }  
  26. else 
  27. {  
  28. bllTable = repositoryBase.Get(key ?? 0);  
  29. }  
  30. this.UpdateModel(bllTable, true);  
  31. if (key == null)  
  32. {  
  33. Context.GetContext().GetTable(repositoryBase.EntityType).InsertOnSubmit(bllTable);  
  34. }  
  35. Context.GetContext().SubmitChanges();  
  36. return RedirectToAction(partialName+"List");//返回到list  

这里边大家可能有疑问的就是this.UpdateModel(bllTable, true);这个方法在mvc框架中并不存在,这是我添加的扩展方法,这个地方如果使用UpdateModel(bllTable)虽然编译不会报错,但也没有更新成功,查了一下mvc的源码,问题就出在如下源码中:

  1. protected internal bool TryUpdateModel(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IDictionary<string, ValueProviderResult> valueProvider) where TModel : class {  
  2. if (model == null) {  
  3. throw new ArgumentNullException("model");  
  4. }  
  5. if (valueProvider == null) {  
  6. throw new ArgumentNullException("valueProvider");  
  7. }  
  8.  
  9. Predicate<string> propertyFilter = propertyName => BindAttribute.IsPropertyAllowed(propertyName, includeProperties, excludeProperties);  
  10. IModelBinder binder = Binders.GetBinder(typeof(TModel));  
  11.  
  12. ModelBindingContext bindingContext = new ModelBindingContext() {  
  13. Model = model,  
  14. ModelName = prefix,  
  15. ModelState = ModelState,  
  16. ModelType = typeof(TModel),  
  17. PropertyFilter = propertyFilter,  
  18. ValueProvider = valueProvider  
  19. };  
  20. binder.BindModel(ControllerContext, bindingContext);  
  21. return ModelState.IsValid;  

这个typeof(TModel)造成了只会更新声明类型中有的属性,把它换成model.GetType()就可以解决问题了,我扩这的这个方法如下

  1. public static class ControllerExtension  
  2. {  
  3. ///   
  4. /// 更新时是否按照当前类型进行更新  
  5. /// 
  6.  
  7. ///   
  8. ///   
  9. ///   
  10. ///   
  11. public static void UpdateModel(this Controller controller, TModel model, bool isExtension) where TModel : class 
  12. {  
  13. if (isExtension)  
  14. {  
  15. Predicate<string> propertyFilter = propertyName => IsPropertyAllowed(propertyName, nullnull);  
  16. IModelBinder binder = ModelBinders.Binders.GetBinder(model.GetType());  
  17.  
  18. ModelBindingContext bindingContext = new ModelBindingContext()  
  19. {  
  20. Model = model,  
  21. ModelName = null,  
  22. ModelState = controller.ModelState,  
  23. ModelType = model.GetType(),  
  24. PropertyFilter = propertyFilter,  
  25. ValueProvider = controller.ValueProvider  
  26. };  
  27. binder.BindModel(controller.ControllerContext, bindingContext);  
  28.  
  29. }  
  30. else 
  31. {  
  32. throw new Exception("isExtension不能选择false");  
  33. }  
  34. }  
  35. private static bool IsPropertyAllowed(string propertyName, string[] includeProperties, string[] excludeProperties)  
  36. {  
  37. bool includeProperty = (includeProperties == null) || (includeProperties.Length == 0) || includeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase);  
  38. bool excludeProperty = (excludeProperties != null) && excludeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase);  
  39. return includeProperty && !excludeProperty;  
  40. }  

有了这些,当我们想对新表进行编辑和添加时只需要添加相应的Partial编辑视图就可以了,简化了我们的编程工作。

四、缺点

1、须要按照规则命名,比方说Partial视图需要以相应的类名来命名

2、页面引用是弱类型的

原文标题:在ASP.NET MVC中对表进行通用的增删改

链接:http://www.cnblogs.com/nuaalfm/archive/2009/11/11/1600811.html

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...