在ASP.NET MVC中对表进行通用的增删改

简介:

预备知识:

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 { getset; }
    }

然后让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、页面引用是弱类型的
五、 源码下载

本文转自 你听海是不是在笑 博客园博客,原文链接:http://www.cnblogs.com/nuaalfm/archive/2009/11/11/1600811.html   ,如需转载请自行联系原作者
相关文章
|
2月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
35 7
|
2月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
48 0
|
3月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
42 0
|
3月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
3月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
113 0
|
6月前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
75 0
|
前端开发 数据安全/隐私保护
net MVC中的模型绑定、验证以及ModelState
net MVC中的模型绑定、验证以及ModelState 模型绑定 模型绑定应该很容易理解,就是传递过来的数据,创建对应的model并把数据赋予model的属性,这样model的字段就有值了。
1690 0
|
6月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
178 0
|
6月前
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
315 5
|
6月前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界