当我们运用 Microsoft Visual Studio 开发一个 ASP.NET MVC 网站的时分,发明可使用一个实体框架(Entity Framework) DbContext 和 用于主动生成代码的 Visual Studio Tools,很轻易的为我们数据库中的每一个表创立把持器和视图. 不外,当数据库中包括很多(查过20)个数据表时,如许一个一个的生成把持器就有点使人腻烦了. 这就是为何我们今日要带来这个处理计划.
为了能不实行修正,就把我们为本文预备的代码跑起来,你需求恪守以下规矩:
确保你的数据库设计中,一切的数据表都有一个作为主键的叫做“id”的“标识域”.
确保一切的外键称号都以”_id“开头.
确保在你的 ADO.NET 实体模子中,一切援用了外键数据工具的属性,都具有没有最初“_id”后缀的对应外键域称号.
确保一切只要两个域(id和别的一个值)的数据表中,别的一个非主键域的称号被设置成 "name".
中止经过DbContext的代办署理类的主动创立。
这项技术能让我们可以再运转形态充沛反省组件和类型,以获得其属性,域,办法,结构器和一个类型的诸多信息.
这些才能关于告竣我们的目的,其主要性是明显的: 经过类型称号可以获得到一个工具,继而可以创立一个用于添加/修正此工具的视图,和一个用于处置怎么显示列表、添加、修正和从数据库删除这些工具的把持器.
起首要做的,是像下面如许修正 RouteConfig.cs 文件,将用于实行普通恳求的默许路由改掉:
routes.MapRoute("Generic", "{lang}/{controller}/{action}/{type}/{id}", new { lang = "en", controller = "Generic", action = "AllClasses", type = UrlParameter.Optional, id = UrlParameter.Optional });
如今,我们可以在使用顺序中创立 "GenericController",来处置一切形如 ~/{language}/Generic/Action/some_type/some_entity_id 的恳求.
我们创立一个没有读写举措的叫做Generic的MVC把持器. 如今,我们将要创立一个接口 IGenEntity ,它外面定义了一个叫做Id的整型属性. 项目中DbContext的一切实体都必需有Id属性作为主键,而且完成 IGenEntity 接口. 在数据库的一切数据表中,这一属性必需被设置成自增加的“标识列”. 并且,数据库中一切外键域的称号都必需当前缀“_id”开头.
一Start编码,我们应当创立一个包括四个能辨别前往用于显示列表、创立、更新和删除数据库工具的视图的办法 (我们建议创立一个没有完成读写举措的MVC把持器) ,然后我们重写初始化(Initialize)办法,以(经过反射)加载以后组件中一切完成了IGenEntity的类型. 如许做的目标是为了列出能展现和静态地加载我们的app中DbContext工具的数据聚集的可用类型.
下图向我们展现了本文所运用的数据库的构造:
如今,我们向模子(model)类中添加一个映照到此数据库的叫做 Articles 的 ADO.NET 实体数据模子. 中的额的edmx文件看起来就像下面如许:
一切的 T4 模板都转换好了,我们就在每个完成了IGenEntity接口,而且重写了ToString函数以定义哪一个值会用于下来列表来展现值,如许的模子中创立一个二次定义. 关于author工具,其二次定义以下所示:
public partial class author: IGenEntity { public override string ToString(){ return firstname+" "+lastname; } }
继而是 GenericController, 其属性和初始化(Initialize)办法应当像下面如许实行完成:
protected override void Initialize(RequestContext requestContext) { base.Initialize(requestContext); db = new ArticlesEntities(); db.Configuration.ProxyCreationEnabled = false; IEntTypes = Assembly.GetAssembly(typeof(IGenEntity)) .GetTypes() .Where(i => i.GetInterfaces().Any(j => j == typeof (IGenEntity))) .ToList(); }
我们向GenericController添加了一个展现一切(完成了IGenEntity的)可用类型的清单的视图,它会将 IEntTypes 属性作为视图模子实行通报.
视图的代码对它本人实行了描绘.
[GenericAuthorize("AllClasses", "Generic")] public ActionResult Index(string type, string id) { if (rtype == null) // If the requested type is not in the list, redirect to the available classes list return RedirectToAction("AllClasses"); int page; // Try to get the requested page number if (!int.TryParse(id, out page)) { page = 1; } // get the set of the DbContext casted as IGenEntity set var set = Enumerable.Cast<IGenEntity>(db.Set(rtype)).OrderBy(i => i.id).AsEnumerable(); // paginate the results if (page != 1) set = set.Skip((page - 1) * pagesize); set = set.Take(pagesize); // save Pages information in the ViewBag ViewBag.CurrentPage = page; // save the number of pages availables ViewBag.Pages = Math.Ceiling(Enumerable.Cast<IGenEntity>(db.Set(rtype)).OrderBy(i => i.id).AsEnumerable().Count() / (double)pagesize); // return the View var result = set.ToList(); foreach (var entity in result) { entity.LoadForeingValues(db); } return View(result); }
视图的代码可以再本文的源代码中找到.
我们必需为这两个获得一个工具模子(Model)、其类型和其属性的函数生成一个 _Edit 视图,并在一个表单(form)中生成一切的必填字段(域 field). 为了让这成为可能, 我们获得了需求的类型和实体,对一切不是否是聚集,和称号不是以“_id”后缀开头的属性. 关于援用工具,我们必需加载全部数据表,来展现一个带有选项的下拉控件.
在把持器的代码中,我们必需经过默许的结构器来生成需要的工具,并用来自表单的值来填充它一切的属性.
实行填充操作的代码以下:
private void SetupTypeAndProperties(Type rtype, string lang) { // Save the type ViewBag.Type = rtype; if (rtype == null) return; // get the properties var props = rtype.GetProperties(); // filter the properties excluding foreing key fields (not objects) var displayProps = props. Where(i => !i.GetGetMethod().ReturnType.Name.Contains("Collection")). Where(i => !i.Name.EndsWith("_id") || (i.Name.EndsWith("_id") && props.All(j => j.Name != i.Name.Replace("_id", "")))). ToList(); ViewBag.Properties = displayProps; var fpath = Server.MapPath("~/App_Data/" + lang + "/classes_info/" + rtype.Name + ".xml"); Expression<Func<XAttribute, string>> selectIfNotNull = i => i != null ? i.Value : null; var c = selectIfNotNull.Compile(); if (System.IO.File.Exists(fpath)) { // Load the metadata from XML file var xel = XElement.Load(fpath); var results = (from i in xel.Descendants("group") let k = (from j in i.Descendants("property") select new PropertyDisplayInfo { Name = c.Invoke(j.Attribute("name")), DisplayName = c.Invoke(j.Attribute("display-name")), Order = int.Parse(c.Invoke(j.Attribute("group-order"))), Type = c.Invoke(j.Attribute("type")), IndexVisible = c.Invoke(j.Attribute("index-visible")) == "true", SelfUpdate = c.Invoke(j.Attribute("self-update")) == "true", PInfo = props.Any(ij => ij.Name == c.Invoke(j.Attribute("name")) + "_id") ? // Search for a foreing key associated property props.First(ij => ij.Name == c.Invoke(j.Attribute("name")) + "_id") : // if is not present then take the self property props.First(ij => ij.Name == c.Invoke(j.Attribute("name"))), PInfo2 = displayProps.Any(ij => ij.Name == c.Invoke(j.Attribute("name")) ) ? // Search for a foreing key associated property props.First(ij => ij.Name == c.Invoke(j.Attribute("name")) ) : // if is not present then take the self property null }).ToList() select new GroupDisplayInfo { Name = i.Attribute("name").Value, Order = int.Parse(i.Attribute("order").Value), Properties = k }); // Save the info in the ViewBag ViewBag.FieldsInfo = results.ToList(); } }
请留意只要几品种型是在switch语句中指定的,而工夫(DateTime)格局被假定成是HTML5格局的.
这就十分容易了:
[HttpPost] [GenericAuthorize("Index", "Generic")] public ActionResult Delete(string type, int id, FormCollection collection) { try { var stype = (Type)ViewBag.Type; db.Set(stype).Remove(Enumerable.Cast<IGenEntity>(db.Set(stype)).First(i => i.id == id)); db.SaveChanges(); return RedirectToAction("Index", new RouteValueDictionary() { { "id", 1 }, { "type", type } }); } catch (Exception ee) { //Save the exception ViewBag.Exception = ee; return RedirectToAction("Delete", new RouteValueDictionary() { { "id", id }, { "type", type } }); } }
这一源项目将会依照一切用户的建议实行更新.
本文中的一切译文仅用于进修和交换目标,转载请务必注明文章译者、出处、和本文链接。 2KB翻译任务按照 CC 协议,假如我们的任务有进犯到您的权益,请实时联络我们。2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务