一起谈.NET技术,详解ASP.NET MVC 2中的新ADO.NET实体框架

简介:   .NET框架4.0的发行推出了许多优秀的增强功能,其中当首推ADO.NET实体框架。该框架已经克服了以前的许多错误,并提供了一组增强的API,其中包括许多新的LINQ to SQL框架方面的改善。在本文中,我们将使用这些API的功能来创建一个通用版本的数据仓库。

  .NET框架4.0的发行推出了许多优秀的增强功能,其中当首推ADO.NET实体框架。该框架已经克服了以前的许多错误,并提供了一组增强的API,其中包括许多新的LINQ to SQL框架方面的改善。在本文中,我们将使用这些API的功能来创建一个通用版本的数据仓库。

  一、实体框架概述

  实体框架针对数据模型提供了一些更方便的操作方法。默认情况下,设计器可以生成一个描述数据库的模型。

尽管表格间的映射未必都是1:1的映射。每个表格使用一个ObjectSet加以描述,进而ObjectSet对象又提供了相应的方法来创建、更新或反射实体和实体间的关系。实体框架使用一个实体键(这是一个看上去像EntitySet=Customers;CustomerID=4的值)来唯一标识模型内的一个实体及其标识符。使用实体键,我们就有了一个方法来更新对象、从数据库中查询的对象,等等。

  二、创建和更新

  让我们首先来看一个基类示例仓库的实现。我想分别地讨论CRUD操作,首先来学习创建和更新操作。

  清单1:创建/更新操作

 
 
1 . public abstract class BaseRepository < T > : IRepository < T >
2 . where T : EntityObject
3 . {
4 . public virtual bool CreateNew(T entity)
5 . {
6 . if (entity == null )
7 . throw new ArgumentNullException( " entity " );
8 . var ctx = CreateContext();
9 . try
10 . {
11 . ctx.AddObject( this .GetFullEntitySetName(ctx), entity);
12 . ctx.SaveChanges();
13 . return true ;
14 . }
15 . catch (Exception ex) { .. }
16 . }
17 . protected abstract string GetEntitySetName(AdventureWorksObjectContext context);
18 . public virtual bool Update(T entity)
19 . {
20 . if (entity == null )
21 . throw new ArgumentNullException( " entity " );
22 . var ctx = CreateContext();
23 . entity.EntityKey = ctx.CreateEntityKey( this .GetFullEntitySetName(ctx),
24 . entity);
25 . try
26 . {
27 . T oldEntity = (T)ctx.GetObjectByKey(entity.EntityKey);
28 . if (oldEntity == null ) return false ;
29 . ctx.ApplyCurrentValues( this .GetFullEntitySetName(ctx), entity);
30 . ctx.SaveChanges();
31 . return true ;
32 . }
33 . catch (Exception ex) { .. }
34 . }
}

  上述代码中,我们的BaseRepository类使用ObjectContext类(需要使用CreateContext方法创建每一个请求)和AddObject方法实现添加新的对象,而通过使用ObjectContext类和AttachTo方法实现更新现有的对象。对于创建对象而言,我们需要知道要更新哪种类型的方法。使用我们的助理GetFullEntitySetName方法可以很好地处理这个问题。这个方法能够返回要添加的标识实体的对象(一个如DotNetSamplesObjectContext.Customers的值)的标识。

  对于更新一个对象而言,我们遇到了与上下文有关的问题。每个从数据库中查询的对象都使用ObjectStateManager类中的ObjectContext成员进行跟踪。MVC绑定过程实际上已经构建了它自己的对象副本,并通过反射把这些值注入到此对象中。这意味着我们有一个新的对象,而不是附加到ObjectContext上的对象。

  这不是一个大问题,我们首先需要查询旧记录。这将为我们的实体生成一个ObjectStateEntry,并且我们可以成功地执行更新(因为它需要知道旧记录是什么)。该实体还需要使用一个EntityKey实体,提供适当的主键信息(记住,EntityKey是确定出已存在的实体的唯一的方式)。

  最后,调用ApplyCurrentValues能够把MVC框架所创建的新的实体值应用到旧实体上。在这里,我们仍然需要使用实体集的名称来唯一标识它。

  三、元数据

  在上面代码中,我们看到了实体集名称的使用方法,用来确定ADO.NET实体框架中的实体的类型。例如,它可以用于描述Products表和Product实体之间的一个映射。还例如,对于我们的产品信息库来说,它可以执行下列操作以获取实体集。

  清单2—返回产品实体集名称

 
 
1 . protected override Expression < Func < DA.Product, object >>
        GetDefaultSortingExpression()
2 . {
3 . return j => j.ProductID;
4 . }
5 . protected override string GetEntitySetName(AdventureWorksObjectContext context)
6 . {
7 . return context.Products.EntitySet.Name;
8 . }

  我们很快将会看到GetDefaultSortingExpression的使用。请注意,这里的GetFullEntitySetName方法把对象的上下文名称追加到实体集名称的后面,以取得添加,更新等操作对应对象的正确名称。 

  四、数据检索

  一般地,我们还可以执行一些读取操作,如下所示。

  清单3—从数据库读取数据

 
 
1 . protected virtual string GetKeyProperty()
2 . {
3 . PropertyInfo[] properties = typeof (T).GetProperties();
4 . foreach (PropertyInfo property in properties)
5 . {
6 . EdmScalarPropertyAttribute attrib = property.GetCustomAttributes
7 . ( typeof (EdmScalarPropertyAttribute), false ).FirstOrDefault()
          as
EdmScalarPropertyAttribute;
8 . if (attrib != null && attrib.EntityKeyProperty)
9 . return property.Name;
10 . }
11 . return null ;
12 . }
13 . public virtual T Get( int key)
14 . {
15 . string prop = this .GetKeyProperty();
16 . if ( string .IsNullOrEmpty(prop))
17 . return null ;
18 . var ctx = CreateContext();
19 . return (T)ctx.GetObjectByKey( new EntityKey( this .GetFullEntitySetName(ctx),
20 . prop, key));
21 . }
22 . public virtual IQueryable < T > GetAll( int pageIndex, int pageSize)
23 . {
24 . var ctx = CreateContext();
25 . return ctx.CreateObjectSet < T > ( this .GetFullEntitySetName(ctx)).OrderBy(
        
this .GetDefaultSortingExpression())
26 . .Skip(pageIndex * pageSize).Take(pageSize);
27 . }

  默认设计器生成的每个实体类都将把一组属性添加到它对应的每一个字段属性上。其中,EdmScalarPropertyAttribute拥有EntityKeyProperty设置,被设置为true,对应于实体的键字段。这就提供了一种灵活的方式来确定主键列而不需要使用一个lambda表达式手动指定。

  跟踪分析到ObjectContext方法内部,你会发现通过使用实体集名称构造一个对象集合可以取得一个数据实体的所有结果。对象集可以使用LINQ扩展方法来按索引页和大小加以过滤,例如只取得一个包含20个对象的结果集。不幸的是,调用Skip和Take方法需要先对对象进行排序。同样,你需要使用一个自定义Lambda表达式来执行这个排序操作。

  GetObjectByKey方法实际上使用它的键从它的数据库中检索对象。我们可以利用我们的新的GetKeyProperty反射方法来获取主键属性的名称。正如你所看到的,我们不能直接使用这个键而需要使用一个EntityKey对象来检索它。

  五、最终实现

  我可以利用一个类似下面的信息库,并且已经在基类中实现了Create、Delete、Update、Get和GetAll方法。我们只需要关心的是,实现其他的查询操作。

  清单4—最终版本的数据仓库类(其他其他前面已列举的内容)

 
 
1 . public class ProductsRepository : BaseRepository < DA.Product >
2 . {
3 . protected override Expression < Func < DA.Product, object >>
           GetDefaultSortingExpression()
4 . {
5 . return j => j.ProductID;
6 . }
7 . protected override string
         GetEntitySetName(DA.DotNetSamplesObjectContext context)
8 . {
9 . return context.Products.EntitySet.Name;
10 . }
11 . }

  在大多数情况下,代码生成将是最好的选择,有助于减少重复代码,但是,实体框架做了大量的内部基础工作(实现基础代码的自动生成)来实现这些特征支持而无需我们编写任何代码。

  六、结论

  ADO.NET实体框架提供了大量基础功能,节省了开发人员大量的代码编写时间。在本文中,我们讨论了ObjectContext类提供给我们的许多方法,其中包括从后端数据库获取和存入数据,等等。

  最后,我们有理由相信,ADO.NET实体框架必将在ASP.NET MVC框架应用程序开发的数据管理模型开发中发挥越来越大的作用。

目录
相关文章
|
1天前
|
JSON 前端开发 Java
【JavaEE】让“单车变摩托”的神级框架—Spring MVC的深入讲解(下)
【JavaEE】让“单车变摩托”的神级框架—Spring MVC的深入讲解
6 0
|
1天前
|
JSON 前端开发 Java
【JavaEE】让“单车变摩托”的神级框架—Spring MVC的深入讲解(上)
【JavaEE】让“单车变摩托”的神级框架—Spring MVC的深入讲解
5 0
|
2天前
|
前端开发 Java Spring
Java Web ——MVC基础框架讲解及代码演示(下)
Java Web ——MVC基础框架讲解及代码演示
12 1
|
2天前
|
设计模式 前端开发 网络协议
Java Web ——MVC基础框架讲解及代码演示(上)
Java Web ——MVC基础框架讲解及代码演示
6 0
|
2天前
|
前端开发 Java 应用服务中间件
Spring MVC框架概述
Spring MVC 是一个基于Java的轻量级Web框架,采用MVC设计模型实现请求驱动的松耦合应用开发。框架包括DispatcherServlet、HandlerMapping、Handler、HandlerAdapter、ViewResolver核心组件。DispatcherServlet协调这些组件处理HTTP请求和响应,Controller处理业务逻辑,Model封装数据,View负责渲染。通过注解@Controller、@RequestMapping等简化开发,支持RESTful请求。Spring MVC具有清晰的角色分配、Spring框架集成、多种视图技术支持以及异常处理等优点。
16 1
|
2天前
|
人工智能 自然语言处理 算法
分享几个.NET开源的AI和LLM相关项目框架
分享几个.NET开源的AI和LLM相关项目框架
|
2天前
|
人工智能 开发框架 量子技术
【专栏】.NET 技术:驱动创新的力量
【4月更文挑战第29天】.NET技术,作为微软的开发框架,以其跨平台、开源和语言多样性驱动软件创新。它在云计算、AI/ML、混合现实等领域发挥关键作用,通过Azure、ML.NET等工具促进新兴技术发展。未来,.NET将涉足量子计算、微服务和无服务器计算,持续拓宽软件开发边界,成为创新的重要推动力。掌握.NET技术,对于开发者而言,意味着握有开启创新的钥匙。
|
2天前
|
开发框架 .NET C#
【专栏】理解.NET 技术,提升开发水平
【4月更文挑战第29天】本文介绍了.NET技术的核心概念和应用,包括其跨平台能力、性能优化、现代编程语言支持及Web开发等特性。文章强调了深入学习.NET技术、关注社区动态、实践经验及学习现代编程理念对提升开发水平的重要性。通过这些,开发者能更好地利用.NET构建高效、可维护的多平台应用。
|
2天前
|
机器学习/深度学习 vr&ar 开发者
【专栏】.NET 技术:引领开发新方向
【4月更文挑战第29天】本文探讨了.NET技术如何引领软件开发新方向,主要体现在三方面:1) 作为跨平台开发的先锋,.NET Core支持多操作系统和移动设备,借助.NET MAUI创建统一UI,适应物联网需求;2) 提升性能和开发者生产力,采用先进技术和优化策略,同时更新C#语言特性,提高代码效率和可维护性;3) 支持现代化应用架构,包括微服务、容器化,集成Kubernetes和ASP.NET Core,保障安全性。此外,.NET还不断探索AI、ML和AR/VR技术,为软件开发带来更多创新可能。
|
2天前
|
开发框架 Cloud Native 开发者
【专栏】剖析.NET 技术的核心竞争力
【4月更文挑战第29天】本文探讨了.NET框架在软件开发中的核心竞争力:1) .NET Core实现跨平台与云原生技术的融合,支持多操作系统和容器化;2) 提升性能和开发者生产力,采用JIT、AOT优化,提供C#新特性和Roslyn编译器平台;3) 支持现代化应用架构,包括微服务和容器化,内置安全机制;4) 丰富的生态系统和社区支持,拥有庞大的开发者社区和微软的持续投入。这些优势使.NET在竞争激烈的市场中保持领先地位。