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

预备知识:

1、了解反射技术

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

3、了解ASP.NET MVC

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

一、准备工作:

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

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

Code
public  interface ICommonTable
    {
        int id { get; set; }
    }

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


Code
 public partial class News : ICommonTable
    {     }
    public partial class User : ICommonTable
    {
       
    }

二、通用删除操作

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

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

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

<%= Html.ActionLink("删除", "Delete", new { key = item.id, partialName="User" })%>
然后添加一个Controller:

 public ActionResult Delete(string partialName, int? key)
        {
            RepositoryBase repositoryBase = new RepositoryBase(partialName);
            repositoryBase.Delete(key ?? 0);
            return RedirectToAction(partialName + "List");//返回到list
        }
接下来我们介绍一下RepositoryBase :

   public class RepositoryBase
    {
        public Type EntityType { get; private set; }
        public RepositoryBase(string entityType)
        {
            Type type = GetBllTypeByName(entityType);             EntityType = type;
        }
        public ICommonTable CreateNew()
        {
            return (ICommonTable)Activator.CreateInstance(EntityType);
        }
        /// <summary>
        /// 通过字符串获得其Type
        /// </summary>
        /// <param name="typeName"></param>
        /// <returns></returns>
        private static Type GetBllTypeByName(string typeName)
        {
            Type type = null;
            var ass = AppDomain.CurrentDomain.GetAssemblies()
                 .Where(p => p.FullName.Contains("CommonCEDemo"));
            foreach (var a in ass)
            {
                type = a.GetTypes().Where(p => p.Name == typeName).FirstOrDefault();
                if (type != null)
                    break;
            }             if (type == null)
            {
                throw new Exception("类型未定义:" + typeName);
            }
            return type;
        }
        public RepositoryBase(Type entityType)
        {
            EntityType = entityType;
        }
        public ICommonTable Get(int id)
        {
            DBDataContext db = Context.GetContext();
            return db.GetTable(EntityType).Cast<ICommonTable>().FirstOrDefault(p => p.id == id);
        }
        public void Delete(int id)
        {
            ICommonTable bllTable = Get(id);
            Context.GetContext().GetTable(EntityType).DeleteOnSubmit(bllTable);
            Context.GetContext().SubmitChanges();
        }
       
    }
 
这里边重点要理解的就是GetBllTypeByName方法。有了这个方法我们就可以动态的通过名字获得相应的Type了。这里还有个问题就是DataContext是从何而来的,我们这里为了简单起见全程声明了一个DataContext没有考虑多线程的情况

public class Context
{
    static DBDataContext context;
    static Context()
    {
        if (context==null)
        {
            context = new DBDataContext();
        }
    }
    public static DBDataContext GetContext()
    {
        return context;
    }
}
 

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

三、通用增加、修改
首先添加一个CreateEditView.aspx视图
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <%Html.RenderPartial(ViewData["PartialName"].ToString()); %>

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

 public ActionResult CreateEditView(string partialName, int? key)
        {             ViewData["PartialName"] = partialName;             RepositoryBase repositoryBase = new RepositoryBase(partialName);
            ICommonTable table;
            if (key == null)
            {
                table = repositoryBase.CreateNew();
            }
            else
            {
                table = repositoryBase.Get(key ?? 0);
            }             return View("CreateEditView", table);
        }         [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult CreateEditView(string partialName, int? key, FormCollection formCollection)
        {
            RepositoryBase repositoryBase = new RepositoryBase(partialName);
            ICommonTable bllTable;
            if (key == null)
            {
                bllTable = repositoryBase.CreateNew();
            }
            else
            {
                bllTable = repositoryBase.Get(key ?? 0);
            }             this.UpdateModel(bllTable, true);
            if (key == null)
            {
                Context.GetContext().GetTable(repositoryBase.EntityType).InsertOnSubmit(bllTable);             }             Context.GetContext().SubmitChanges();             return RedirectToAction(partialName+"List");//返回到list
        }
 
这里边大家可能有疑问的就是this.UpdateModel(bllTable, true);这个方法在mvc框架中并不存在,这是我添加的扩展方法,这个地方如果使用UpdateModel(bllTable)虽然编译不会报错,但也没有更新成功,查了一下mvc的源码,问题就出在如下源码中:

 protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IDictionary<string, ValueProviderResult> valueProvider) where TModel : class {
            if (model == null) {
                throw new ArgumentNullException("model");
            }
            if (valueProvider == null) {
                throw new ArgumentNullException("valueProvider");
            }             Predicate<string> propertyFilter = propertyName => BindAttribute.IsPropertyAllowed(propertyName, includeProperties, excludeProperties);
            IModelBinder binder = Binders.GetBinder(typeof(TModel));             ModelBindingContext bindingContext = new ModelBindingContext() {
                Model = model,
                ModelName = prefix,
                ModelState = ModelState,
                ModelType = typeof(TModel),
                PropertyFilter = propertyFilter,
                ValueProvider = valueProvider
            };
            binder.BindModel(ControllerContext, bindingContext);
            return ModelState.IsValid;
        }
 

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


public static class ControllerExtension
    {
        /// <summary>
        /// 更新时是否按照当前类型进行更新
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="controller"></param>
        /// <param name="model"></param>
        /// <param name="isEx"></param>
        public static void UpdateModel<TModel>(this Controller controller, TModel model, bool isExtension) where TModel : class
        {
            if (isExtension)
            {
                Predicate<string> propertyFilter = propertyName => IsPropertyAllowed(propertyName, null, null);
                IModelBinder binder = ModelBinders.Binders.GetBinder(model.GetType());                 ModelBindingContext bindingContext = new ModelBindingContext()
                {
                    Model = model,
                    ModelName = null,
                    ModelState = controller.ModelState,
                    ModelType = model.GetType(),
                    PropertyFilter = propertyFilter,
                    ValueProvider = controller.ValueProvider
                };
                binder.BindModel(controller.ControllerContext, bindingContext);             }
            else
            {
                throw new Exception("isExtension不能选择false");
            }
        }
        private static bool IsPropertyAllowed(string propertyName, string[] includeProperties, string[] excludeProperties)
        {
            bool includeProperty = (includeProperties == null) || (includeProperties.Length == 0) || includeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase);
            bool excludeProperty = (excludeProperties != null) && excludeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase);
            return includeProperty && !excludeProperty;
        }
    }
 

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

四、缺点
1、须要按照规则命名,比方说Partial视图需要以相应的类名来命名
2、页面引用是弱类型的
 

在ASP.NET MVC中对表进行通用的增删改的更多相关文章

  1. 【转载】ASP.NET MVC Web API 学习笔记---联系人增删改查

    本章节简单介绍一下使用ASP.NET MVC Web API 做增删改查.目前很多Http服务还是通过REST或者类似RESP的模型来进行数据操作的.下面我们通过创建一个简单的Web API来管理联系 ...

  2. ASP.NET MVC Web API 学习笔记---联系人增删改查

    本章节简单介绍一下使用ASP.NET MVC Web API 做增删改查. 目前很多Http服务还是通过REST或者类似RESP的模型来进行数据操作的. 下面我们通过创建一个简单的Web API来管理 ...

  3. 3、ASP.NET MVC入门到精通——Entity Framework增删改查

    这里我接上讲Entity Framework入门.从网上下载Northwind数据库,新建一个控制台程序,然后重新添加一个ado.net实体数据模型. EF中操作数据库的"网关"( ...

  4. asp.net mvc 三层加EF 登录注册 增删改查

    首先打开vs软件新建项目创建web中的mvc项目再右击解决方案创建类库项目分别创建DAL层和BLL层再把DAL层和BLL层的类重命名在mvc项目中的Models文件夹创建model类在DAL创建ADO ...

  5. Asp.net mvc中的Ajax处理

    在Asp.net MVC中的使用Ajax, 可以使用通用的Jquery提供的ajax方法,也可以使用MVC中的AjaxHelper. 这篇文章不对具体如何使用做详细说明,只对于在使用Ajax中的一些需 ...

  6. ASP.NET MVC 中使用 AjaxFileUpload 插件时,上传图片后不能显示(预览)

    AjaxFileUpload 插件是一个很简洁很好用的上传文件的插件,可以实现异步上传功能,但是在 ASP.NET MVC中使用时,会出现上传图片后不能正确的显示的问题,经过仔细排查,终于找到原因,解 ...

  7. 在ASP.NET MVC 中获取当前URL、controller、action 、参数

    URL的获取很简单,ASP.NET通用:[1]获取 完整url (协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [2]获取 虚拟目录名 ...

  8. ASP.NET MVC中注册Global.asax的Application_Error事件处理全局异常

    在ASP.NET MVC中,通过应用程序生命周期中的Application_Error事件可以捕获到网站引发的所有未处理异常.本文作为学习笔记,记录了使用Global.asax文件的Applicati ...

  9. 2.ASP.NET MVC 中使用Crystal Report水晶报表

    上一篇,介绍了怎么导出Excel文件,这篇文章介绍在ASP.NET MVC中使用水晶报表. 项目源码下载:https://github.com/caofangsheng93/CrystalReport ...

随机推荐

  1. 记录一次redis故障

    ResponseError: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persi ...

  2. PHP的垃圾回收

    PHP使用引用计数和写时拷贝(Copy-On-Write)来管理内存. 引用技术不言自明,写时拷贝工作原来如下: $worker = array("Fred", 35, " ...

  3. D.王者荣耀交流协会——PSP Daily(测评人:贾男男)

    D.王者荣耀交流协会——PSP Daily(测评人:贾男男) 一.基于NABCD评论作品,及改进建议 每个小组评论其他小组beta发布的作品.1.根据(不限于)NABCD评论作品的选题;2.评论作品对 ...

  4. 为什么使彩色图变灰RGB的权重会固定(R:0.299 G:0.587 B:0.114)?

    人眼对绿色的敏感度最高,对红色的敏感度次之,对蓝色的敏感度最低,因此使用不同的权重将得到比较合理的灰度图像.根据实验和理论推导得出以下数值 R: 0.299. G:  0.587. B: 0.114.

  5. Java 多生产者消费者问题

    /* 生产者,消费者.   多生产者,多消费者的问题. if判断标记,只有一次,会导致不该运行的线程运行了.出现了数据错误的情况. while判断标记,解决了线程获取执行权后,是否要运行!   not ...

  6. 运行时错误 429,ACTIVEX部件不能创建对象的解决方法小结

    错误描述: 发布在IIS上面的网站运行时出现如下错误: Microsoft VBscrīpt 运行时错误 错误 '800a01ad' ActiveX 部件不能创建对象 这个错误是asp组件未注册,而导 ...

  7. Vue.js——60分钟webpack项目模板快速入门

    概述 browserify是一个 CommonJS风格的模块管理和打包工具,上一篇我们简单地介绍了Vue.js官方基于browserify构筑的一套开发模板.webpack提供了和browserify ...

  8. Vue.js——60分钟browserify项目模板快速入门

    概述 在之前的一系列vue.js文章,我们都是用传统模式引用vue.js以及其他的js文件的,这在开发时会产生一些问题. 首先,这限定了我们的开发模式是基于页面的,而不是基于组件的,组件的所有代码都直 ...

  9. HBase 架构与工作原理2 - HBase 组件

    本文系转载,如有侵权,请联系我:likui0913@gmail.com 一.HBase 组件概览 Master-Slave 模式: HBase 体系结构遵循传统的 master-slave 模式,由一 ...

  10. ci钩子

    钩子 - 扩展框架核心 CodeIgniter 的钩子特性提供了一种方法来修改框架的内部运作流程,而无需修改 核心文件.CodeIgniter 的运行遵循着一个特定的流程,你可以参考这个页面的 应用程 ...