博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在ASP.NET MVC中对表进行通用的增删改
阅读量:6785 次
发布时间:2019-06-26

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

预备知识:

1、了解反射技术

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

3、了解ASP.NET MVC

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

一、准备工作:

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

2009111110413753.png

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

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

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

ExpandedBlockStart.gif
Code
 public partial class News : ICommonTable
    {
    }
    
public partial class User : ICommonTable
    {
       
    }

二、通用删除操作

分别添加NewsList.aspx和UserList.aspx两个view,添加方式参见

在这两个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
  ,如需转载请自行联系原作者
你可能感兴趣的文章
我的友情链接
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
基础排序算法 – 插入排序Insertion sort
查看>>
Spring mvc ViewResolver视图解析器实现机制
查看>>
源码安装Apache 2.4.18
查看>>
spring--(6)p标签的使用
查看>>
java --泛型
查看>>
怎样将PPT文件转换为Word文档精美ppt模板下载
查看>>
ARM编辑、编译工具
查看>>
数字签名
查看>>
centos7安装docker镜像源管理工具harbor
查看>>
vim工具的编辑模式及命令模式
查看>>
DevExpress v17.2新版亮点——Data Access
查看>>
Java Script 第七节课 Java Script的逻辑运算符的例子
查看>>
CSS 3 伪类选择器
查看>>
swfit学习函数
查看>>
UML状态机
查看>>
Java过滤器,SpringMVC拦截器之间的一顺序点关系
查看>>
决心书
查看>>