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

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

时间: 2024-09-09 14:43:43

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

详解ASP.NET MVC 2中的新ADO.NET实体框架

.NET框架4.0的发行推出了许多优秀的增强功能,其中当首推ADO.NET实体框架.该框架已经克服了以前的许多错误,并提供了一组增强的 API,其中包括许多新的LINQ to SQL框架方面的改善.在本文中,我们将使用这些API的功能来创建一个通用版本的数据仓库. 一.实体框架概述 实体框架针对数据模型提供了一些更方便的操作方法.默认情况下,设计器可以生成一个描述数据库的模型. 尽管表格间的映射未必都是1:1的映射.每个表格使用一个ObjectSet加以描述,进而ObjectSet对象又提供了相

一起谈.NET技术,体验ASP.NET MVC 3中的Razor特性

1 闲话ASP.NET MVC 3 beta 不知道不觉MVC3更新了好几次了...因为一直在弄Silverlight的开发没有时间关注ASP.NET MVC.之前出preview 的时候就看了园子里的一些文章. 但是总觉得"不咋地",依赖注入早就有一套了,全局拦截器也就那么回事..好像都没有对开发效率有太大的提升...(一己之见.目前正在学习MVC3BEAT的DI). 除了RAZOR...  好吧. 现在开始动手吧! 2开工  2.1目录     在_ViewStart.cshtml

一起谈.NET技术,详解ASP.NET MVC数据分页

ASP.NET MVC框架已经进入2.0时代,本文将从ASP.NET MVC数据分页谈起,希望能对大家有所帮助. 在网页上进行表格资料或其他显示资料的分页是一种十分常见的需求,以前我们有 GridView 或 DataPager 可以帮我们自动分页,虽然到了 ASP.NET MVC 一切全部重头来过,但我们也不用真的那麽辛苦的自己实做分页,因为早就有人帮我们写好程式并开放原始码分享给这个世界了. 如果你已经体会到在 ASP.NET MVC 中妥善利用强型别(Strong Typed)特性进行开发

详解ASP.NET MVC数据分页

ASP.NET MVC框架已经进入2.0时代,本文将从ASP.NET MVC数据分页谈起,希望能对大家有所帮助. 在网页上进行表格资料或其他显示资料的分页是一种十分常见的需求,以前我们有 GridView 或 DataPager 可以帮我们自动分页,虽然到了 ASP.NET MVC 一切全部重头来过,但我们也不用真的那麽辛苦的自己实做分页,因为早就有人帮我们写好程式并开放原始码分享给这个世界了. 如果你已经体会到在 ASP.NET MVC 中妥善利用强型别(Strong Typed)特性进行开发

一起谈.NET技术,[翻译]ASP.NET MVC 3 RC 发布通告

今天早上,ASP.NET组发布了ASP.NET 3 RC版(release candidate).你们可以从这里进行下载here. ASP.NET MVC 3是个很完美的发布,增加了大量的功能改进.它可以向后兼容ASP.NET MVC V1 和 V2,可以轻易的升级你现有的项目(可以阅读发布须知,根据里面的步骤去做).你还可以通过我之前发表的博客文章来学习ASP.NET MVC 3的很多功能.  今天的ASP.NET MVC 3 RC build 包含了一些附加的功能改进(除了修正了一些bug外

一起谈.NET技术,在ASP.NET MVC中进行TDD开发

TDD介绍 TDD是一种开发方法,全称是Test-Driven development,中文是测试驱动开发.作者是Kent Beck.首先让我介绍一下三种常见的开发方式: 第一种:先Coding,然后Bug Fix. 第二种:先Coding,然后Unit Test,最后Bug Fix.很显然用了单元测试的比第一种开发方式要好不少. 第三种:就是本文要说的TDD,它的方式和第二种恰恰相反.TDD先设计单元测试,然后再Coding,最后修复Bug.看下图: TDD开发过程可以看成:给制自己制定一个目

领先技术:在ASP.NET MVC 4中创建为移动设备优化的视图

如果深入探讨有关编写移动设备网站的常识性考虑因素,会发现其中有一种内在矛盾.一方面,客户在其 编写应用程序和网站的方法中强烈要求(或乐于要求)移动优先.另一方面,同一些人又经常称赞 CSS 媒体 查询和流体布局.我所发现的矛盾在于经常利用 CSS 媒体查询和流体布局并未在其他内容之前优先处理移动 方面,它不是一种移动优先的方法.在本文中,我将介绍如何使用服务器端逻辑为给定设备呈现最佳的显示效 果,并介绍 ASP.NET MVC 4 的一种新功能,称为显示模式. 问题不在于 CSS 媒体查询作为一

一起谈.NET技术,跟ASP.NET MVC一起使用jQuery

藉由ASP.NET MVC内置的扩展性,开发人员便可以使用第三方库,例如jQuery.在使用ASP.NET Webforms的时候,如果使用jQuery而不是ASP.NET AJAX,难度会比较大. 刚开始撰写本文的时候,ASP.NET MVC的版本是Preview 4,有些在Preview 4中使用的技术可能无法在早期版本中正常工作.Preview 4可以在CodePlex上下载. 初步配置 我不打算把它写成一篇完整的jQuery指南,只是简单给出几个跟ASP.NET MVC一起使用这款Jav

详解Asp.net MVC DropDownLists

Asp.net MVC中的DropDownLists貌似会让一开始从Asp.net Forms转过来的程序员造成不 少迷惑.这篇文章讲述了为了使用DropDownLists,你需要在Asp.Net MVC中知道的方方面 面. DropDownList,ComboBox,无论你喜欢怎么称呼这些,他们毫无例外的会被生成为html select标签. 在<select>开标签和</select>闭标签之间,每一个列表元素都必 须被包裹于<option>标签.当然你也可以使用&