作者的写下此文的背景是一些项目本身规模不大的情况下,也有其他网友担心性能方面的问题。在这里我们先看一下ASP.NET MVC对表是如何进行通用的增删改操作的。
预备知识:
1、了解反射技术
2、了解C#3.0中扩展方法,分布类,Linq to object,Linq to sql
3、了解ASP.NET MVC
在项目中每添加一个表往往都要添加一套增删改代码,而且这些代码很多情况下都很相似,这里我们给出一个通用的解决方案供大家参考。
一、准备工作:
这里我们先要在数据库中添加两个表News和User如下图:然后拖到dbml中生成实体类。
这里我们先准备一个接口:ICommonTable
1 2 3 4 5 6 | <pre class = "brush:c#;toolbar:false;" >Code public interface ICommonTable { int id { get ; set ; } }</pre><p> </p> |
然后让News和User实体都继承于此接口
1 2 3 4 5 6 7 8 | <pre class = "brush:c#;toolbar:false;" >Code public partial class News : ICommonTable { } public partial class User : ICommonTable { }</pre><p> </p> |
二、通用删除操作
分别添加NewsList.aspx和UserList.aspx两个view,添加方式参见ASP.NET MVC实践系列2-简单应用
在这两个View中加入删除链接:
1 2 3 4 | <pre class = "brush:c#;toolbar:false;" ><%= Html.ActionLink( "删除" , "Delete" , new { key = item.id, partialName= "News" })%> 和 <%= Html.ActionLink( "删除" , "Delete" , new { key = item.id, partialName= "User" })%></pre><p> </p> |
然后添加一个Controller:
1 2 3 4 5 6 7 | <pre class = "brush:c#;toolbar:false;" > public ActionResult Delete( string partialName, int ? key) { RepositoryBase repositoryBase = new RepositoryBase(partialName); repositoryBase.Delete(key ?? 0); return RedirectToAction(partialName + "List" ); //返回到list }</pre><p> </p> |
接下来我们介绍一下RepositoryBase :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | <pre class = "brush:c#;toolbar:false;" > 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(); } }</pre><p> </p> |
这里边重点要理解的就是GetBllTypeByName方法。有了这个方法我们就可以动态的通过名字获得相应的Type了。这里还有个问题就是DataContext是从何而来的,我们这里为了简单起见全程声明了一个DataContext没有考虑多线程的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <pre class = "brush:c#;toolbar:false;" > public class Context { static DBDataContext context; static Context() { if (context== null ) { context = new DBDataContext(); } } public static DBDataContext GetContext() { return context; } }</pre><p> </p> |
有个这些当我们想要对一个表进行删除是只要添加相应的链接就可以了(如<%= Html.ActionLink("删除", "Delete", new { key = item.id, partialName="News" })%>)
三、通用增加、修改
首先添加一个CreateEditView.aspx视图
1 2 3 4 | <pre class = "brush:c#;toolbar:false;" ><asp:Content ID= "Content2" ContentPlaceHolderID= "MainContent" runat= "server" > <%Html.RenderPartial(ViewData[ "PartialName" ].ToString()); %> </asp:Content></pre><p> </p> |
然后添加两个Partial视图News.ascx和User.ascx,这两个视图是分别基于News和User类的强类型视图,具体内容参加源码。
接下来我们添加相应的Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <pre class = "brush:c#;toolbar:false;" > 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 }</pre><p> </p> <div style= " display:block; width:100%; padding-top:15px; margin:0px auto; height:90px; overflow:hidden; text-align:center;" ><script src= "/2011/ads/tech_content_end_468x60.js" ></script><script type= "text/javascript" ><!-- google_ad_client = "pub-5977682010997732" ;
google_ad_slot = "4048873275" ; google_ad_width = 468; google_ad_height = 60; //--> </script> <script type= "text/javascript" src= "http://pagead2.googlesyndication.com/pagead/show_ads.js" > </script><ins style= "display:inline-table;border:none;height:60px;margin:0;padding:0;position:relative;visibility:visible;width:468px" ><ins id= "aswift_1_anchor" style= "display:block;border:none;height:60px;margin:0;padding:0;position:relative;visibility:visible;width:468px" ><iframe allowtransparency= "true" hspace= "0" marginwidth= "0" marginheight= "0" onload= "var i=this.id,s=window.google_iframe_oncopy,H=s&&s.handlers,h=H&&H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&&d&&(!d.body||!d.body.firstChild)){if(h.call){i+='.call';setTimeout(h,0)}else if(h.match){i+='.nav';w.location.replace(h)}s.log&&s.log.push(i)}" vspace= "0" id= "aswift_1" name= "aswift_1" style= "left:0;position:absolute;top:0;" scrolling= "no" width= "468" frameborder= "0" height= "60" ></iframe></ins></ins> </div> |