一起谈.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框架应用程序开发的数据管理模型开发中发挥越来越大的作用。

目录
相关文章
|
9天前
|
C# Android开发 iOS开发
2025年全面的.NET跨平台应用框架推荐
2025年全面的.NET跨平台应用框架推荐
57 23
|
26天前
|
开发框架 算法 .NET
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
|
26天前
|
开发框架 Cloud Native .NET
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
|
26天前
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
|
1月前
|
消息中间件 开发框架 监控
NET任务调度框架Hangfire使用指南
Hangfire 是一个用于 .NET 应用程序的开源任务调度框架,支持长时间运行任务、定时任务等。通过简单的安装配置,即可将任务从主线程分离,提升应用性能。支持多种数据库,提供丰富的任务类型如立即执行、延迟执行和周期性任务,并有可视化管理界面 Hangfire Dashboard。还支持安全性配置及扩展插件,如 Hangfire.HttpJob,适合各种复杂场景下的任务调度需求。
77 1
NET任务调度框架Hangfire使用指南
|
2月前
|
机器学习/深度学习 人工智能 Cloud Native
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台。本文深入解析 .NET 的核心优势,探讨其在企业级应用、Web 开发及移动应用等领域的应用案例,并展望未来在人工智能、云原生等方面的发展趋势。
49 3
|
2月前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
50 3
|
2月前
|
开发框架 安全 Java
.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力
本文深入探讨了.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力。.NET不仅支持跨平台开发,具备出色的安全性和稳定性,还能与多种技术无缝集成,为企业级应用提供全面支持。
48 3
|
Web App开发 缓存 网络协议
WCF技术剖析之二:再谈IIS与ASP.NET管道
原文:WCF技术剖析之二:再谈IIS与ASP.NET管道 在2007年9月份,我曾经写了三篇详细介绍IIS架构和ASP.NET运行时管道的文章,深入介绍了IIS 5.x与IIS 6.0HTTP请求的监听与分发机制,以及ASP.
1189 0