2KB项目,专业的源码交易网站 帮助 收藏 每日签到

用于处置 Entity Frameworks 的 DbContext 和工具的 ASP.NET MVC 泛型把持器和视图

  • 时间:2019-05-18 04:55 编辑:2KB 来源:2KB.COM 阅读:411
  • 扫一扫,手机访问
  • 分享
摘要:
Entity Framework ASP.NET MVC 英文原文:ASP.NET MVC Generic controllers and views for handling Entity Frameworks DbContext’s and objects

引见

当我们运用 Microsoft Visual Studio 开发一个 ASP.NET MVC 网站的时分,发明可使用一个实体框架(Entity Framework) DbContext 和 用于主动生成代码的 Visual Studio Tools,很轻易的为我们数据库中的每一个表创立把持器和视图. 不外,当数据库中包括很多(查过20)个数据表时,如许一个一个的生成把持器就有点使人腻烦了. 这就是为何我们今日要带来这个处理计划.

布景

根本的规矩

为了能不实行修正,就把我们为本文预备的代码跑起来,你需求恪守以下规矩:

  • 确保你的数据库设计中,一切的数据表都有一个作为主键的叫做“id”的“标识域”.

  • 确保一切的外键称号都以”_id“开头.

  • 确保在你的 ADO.NET 实体模子中,一切援用了外键数据工具的属性,都具有没有最初“_id”后缀的对应外键域称号.

  • 确保一切只要两个域(id和别的一个值)的数据表中,别的一个非主键域的称号被设置成 "name".

  • 中止经过DbContext的代办署理类的主动创立。

.NET 反射

这项技术能让我们可以再运转形态充沛反省组件和类型,以获得其属性,域,办法,结构器和一个类型的诸多信息.

这些才能关于告竣我们的目的,其主要性是明显的: 经过类型称号可以获得到一个工具,继而可以创立一个用于添加/修正此工具的视图,和一个用于处置怎么显示列表、添加、修正和从数据库删除这些工具的把持器.

运用代码

起首要做的,是像下面如许修正 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();
        }

举措(Action)和视图(View)的把持器

AllClasses 视图

我们向GenericController添加了一个展现一切(完成了IGenEntity的)可用类型的清单的视图,它会将 IEntTypes 属性作为视图模子实行通报.

视图的代码对它本人实行了描绘.

Index 视图

[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);
        }

视图的代码可以再本文的源代码中找到.

创立(Create)和编辑(Edit)举措

我们必需为这两个获得一个工具模子(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格局的.

删除(Delete)举措

这就十分容易了:

[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,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部