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

预备知识:

1、了解反射技术

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

3、了解ASP.NET MVC

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

一、准备工作:

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

2009111110413753.png

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

ContractedBlock.gif ExpandedBlockStart.gif Code
public  interface ICommonTable
    {
        
int id { getset; }
    }

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

ContractedBlock.gif ExpandedBlockStart.gif 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、页面引用是弱类型的
五、 源码下载

转载于:https://www.cnblogs.com/nuaalfm/archive/2009/11/11/1600811.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值