Entity Data Model (EDM) 深入分析, Part 1
 
2008-12-10 来源:EntLib.com
 

Entity Data Model是.NET Framework v3.5 SP1引入的新功能,比Linq To SQL更加强大的ORM,让开发人员只需要着眼于领域对象模型的开发,而不需要考虑它们是如何与关系数据库交互。本系列文章逐步深入介绍如下内容:EDMX Schema 文件、Model Browser、映射关系、产生的实体类(Generated entity classes)、文档(Documentation)等等。

1. EDMX Schema 文件

可以将EDMX作为XML文件打开,你会发现该文件包含3个主要部分。

Conceptual Models (CSDL)
Storage Models (SSDL)
Mapping (MSL)

一般情况下,你没有必要手动修改EDMX -XML文件。可视化的EDM 设计器、Mapping Details窗口和Model Browser 窗口包含有上述3个部分,并非常友好地显示整个Entity Data Model模型。

当你编译项目时,MSBuild 将从EDMX文件提取CSDL/SSDL/MSL内容,并放置3个独立的XML文件到项目的输出目录。

2. Model Browser 窗口

Model Browser窗口以可视的树形图显示概念模型和存储模型。

3. Mapping details 窗口

EDM设计器也提供了一个不错的Mapping Details 窗口,包含2个视图。

Map Entity to Tables / View

这一视图显示了数据库中所有字段和相应实体中的属性,可以用来查看和编辑EDM的映射关系。

Map Entity to Functions

这一视图用来选择一个特定的存储过程来插入、更新或删除Entity实例。


4. 生成的实体类(Generated Entity Classes)

除了上述的XML Schema文件外,EDM向导也生成了实体类。下一步仔细分析.Designer.cs文件中的实体类,并和LINQ to SQL中的类进行比较。

1) 比较 LINQ to SQL class 和 EDM EntityObject class

// LINQ to SQL
[Table(Name="dbo.Employees")]
public partial class Employee : INotifyPropertyChanging, INotifyPropertyChanged
 
EDM类则是以不同的attributes,并且总是继承EntityObject或ComplexObject 类。EntityObject 类提供了变更跟踪和关系管理。
// Entity Data Model
[global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="NorthwindModel", Name="Employee")]
[global::System.Runtime.Serialization.DataContractAttribute()]
[global::System.Serializable()]
public partial class Employee : global::System.Data.Objects.DataClasses.EntityObject

2) 比较LINQ to SQL entity constructor 和 EDM Create method

// LINQ to SQL
public Employee()
{
 this._Employees = new EntitySet<Employee>(new Action<Employee>(this.attach_Employees), new Action<Employee>(this.detach_Employees));
 this._EmployeeTerritories = new EntitySet<EmployeeTerritory>(new Action<EmployeeTerritory>(this.attach_EmployeeTerritories),
    new Action<EmployeeTerritory>(this.detach_EmployeeTerritories));
 this._Orders = new EntitySet<Order>(new Action<Order>(this.attach_Orders), new Action<Order>(this.detach_Orders));
 this._Employee1 = default(EntityRef<Employee>);
 OnCreated();
}
 
EDM没有生成上述LINQ to SQL的构造函数,而是创建了一个特定的Create方法,并提供了所有必需属性(not nullable)的输入参数。
// Entity Data Model
public static Employee CreateEmployee(int employeeID, string lastName, string firstName)
{
    Employee employee = new Employee();
    employee.EmployeeID = employeeID;
    employee.LastName = lastName;
    employee.FirstName = firstName;
    return employee;
}

3) 比较LINQ to SQL 和 EDM : 实体属性(entity property)

// LINQ to SQL
[Column(Storage="_EmployeeID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int EmployeeID
{
 get
 {
    return this._EmployeeID;
 }
 set
 {
   if ((this._EmployeeID != value))
    {
      this.OnEmployeeIDChanging(value);
      this.SendPropertyChanging();
      this._EmployeeID = value;
      this.SendPropertyChanged("EmployeeID");
      this.OnEmployeeIDChanged();
    }
 }
}

尽管EDM公有属性(public property)的attribute是不同的,但get和set 基本是一样的。

// Entity Data Model
[global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
[global::System.Runtime.Serialization.DataMemberAttribute()]
public int EmployeeID
{
    get
    {
        return this._EmployeeID;
    }
    set
    {
        this.OnEmployeeIDChanging(value);
        this.ReportPropertyChanging("EmployeeID");
        this._EmployeeID = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
        this.ReportPropertyChanged("EmployeeID");
        this.OnEmployeeIDChanged();
    }
}

4) 比较LINQ to SQL Table 和 EDM ObjectQuery

// LINQ to SQL
public System.Data.Linq.Table<Employee> Employees
{
 get
 {
    return this.GetTable<Employee>();
 }
}

在LINQ to SQL中,调用GetTable 方法,返回实体集合。在EDM中,通过Object Services compoment 执行Entity SQL 查询,返回EntityType的计划EntitySet。

// Entity Data Model
[global::System.ComponentModel.BrowsableAttribute(false)]
public global::System.Data.Objects.ObjectQuery<Employee> Employees
{
    get
    {
        if ((this._Employees == null))
        {
            this._Employees = base.CreateQuery<Employee>("[Employees]");
        }
        return this._Employees;
    }
}
private global::System.Data.Objects.ObjectQuery<Employee> _Employees;

5) 比较LINQ to SQL DataContext  和 EDM ObjectContext

// LINQ to SQL
[System.Data.Linq.Mapping.DatabaseAttribute(Name="Northwind")]
public partial class NorthwindDataContext : System.Data.Linq.DataContext
 
EDM有一个类似于LINQ to SQL DataContext 的ObjectContext类,ObjectContext 类是负责与EDM 中实体类型交互的基本类。ObjectContext用来创建数据库连接、检索数据、持久化对象、以及对数据库的插入、更新和删除操作。
 
// Entity Data Model
public partial class NorthwindEntities : global::System.Data.Objects.ObjectContext
 
ObjectContext的连接字符串指向元数据(CSDL/SSDL/MSL 文件)和数据源(数据库连接字符串)。
connectionString="metadata=.\NorthwindModel.csdl|.\NorthwindModel.ssdl|.\NorthwindModel.msl;
 provider=System.Data.SqlClient; provider connection string=&quot;
 Data Source=SQLEXPRESS; Initial Catalog=Northwind; Integrated Security=True; MultipleActiveResultSets=True&quot;"

5. Documentation 属性

EDM中的实体类型(EntityTypes)、关联和属性有一个Documentation属性,对LINQ to SQL而言,这是一个新的属性。



  Documentation属性将更新生成的partial实体类的XML注释,可以用来生成代码文档的帮助文件。

/// <summary>
/// Employee entity which corresponds with the Northwind.Employees table
/// </summary>
/// <KeyProperties>
/// EmployeeID
/// </KeyProperties>
[global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="NorthwindModel", Name="Employee")]
[global::System.Runtime.Serialization.DataContractAttribute()]
[global::System.Serializable()]
public partial class Employee : global::System.Data.Objects.DataClasses.EntityObject

火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织