技术开发 频道

巨大转变!ASP.NET MVC2之ADO实体框架

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

  一、实体框架概述

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

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

  二、创建和更新

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

  清单1:创建/更新操作

public abstract class BaseRepository<T> : IRepository<T>
    where T : EntityObject
{
    
public virtual bool CreateNew(T entity)
    {
        
if (entity == null)
            throw
new ArgumentNullException("entity");
        var ctx
= CreateContext();
        try
        {
            ctx.AddObject(this.GetFullEntitySetName(ctx), entity);
            ctx.SaveChanges();
            return
true;
        }
        catch (Exception ex) { .. }
    }
    protected abstract
string GetEntitySetName(AdventureWorksObjectContext context);
    
public virtual bool Update(T entity)
    {
        
if (entity == null)
            throw
new ArgumentNullException("entity");
        var ctx
= CreateContext();
        entity.EntityKey
= ctx.CreateEntityKey(this.GetFullEntitySetName(ctx),
                  entity);
        try
        {
            T oldEntity
= (T)ctx.GetObjectByKey(entity.EntityKey);
            
if (oldEntity == null) return false;
            ctx.ApplyCurrentValues(this.GetFullEntitySetName(ctx), entity);
            ctx.SaveChanges();
            return
true;
        }
        catch (Exception ex) { .. }
    }
}

 

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

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

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

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

  三、元数据

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

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

protected override Expression<Func<DA.Product, object>> GetDefaultSortingExpression()
{
    return j
=> j.ProductID;
}
protected override
string GetEntitySetName(AdventureWorksObjectContext context)
{
    return context.Products.EntitySet.Name;
}

 

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

0
相关文章