What’s New in Entity Framework 4? API Changes(1)(转)

If you have been working with the ADO.NET Entity Framework, you have probably been extremely eager to get your hands on the next version that is now part of Visual Studio 2010 and .NET 4.0. Long referred to as “EF Version 2,” this version is now called Entity Framework 4 or EF4, to align with the .NET Framework 4.0 version.

Microsoft released Visual Studio 2010 Beta 1 in mid-May along with .NET Framework 4.0 Beta 1 and many developers have been digging deeply. VS 2010 offers many new features, but this article will focus on new features and improvements in the ADO.NET Entity Framework (EF). Although this is only the second version of EF, it’s version number is 4, to align with the .NET version, therefore many people call it EF4.

The changes in EF4 include numerous major improvements to the designer, the addition of model-first design, a new way to customize classes that are generated from the model, the ability to create POCOclasses (Plain Old CLR Objects) that can be used in EF without having to be strongly bound to the EF APIs, and additions that will make using entities across processes (e.g. Web services) much easier for developers. I will highlight some of the bigger and more interesting features in the APIs. A future article will highlight designer changes and the tools released in the out of band Feature Pack.

Note that this article is not meant to be a primer on Entity Framework and therefore assumes that you have some experience working with the current version. Yet, rather than give only a high level overview of the new features, this article will give you insights into using a number of the new features.

Generating Custom Classes from a Model

Once you have designed an Entity Data Model, the designer triggers a code generator, which builds classes from the entities defined in the model. In the first version of Entity Framework, this code generation was handled by code in the System.Data.Entity.Design API. If you wanted to customize the generated code, it meant learning that API and writing your own code generation methods-a somewhat cumbersome task. For EF4, the team has leveraged a code generator that was introduced in Visual Studio 2008 called T4 (Text Template Transformation Toolkit). See the Resources sidebar for more information on T4 in general. Using T4 templates makes customizing the generated entity classes enormously simpler.

To demonstrate this, I’ll begin with a simple model to track my bike rides as shown in Figure 1.

 

 

 Figure 1: Starting with a simple model.

 

There are two steps to this customization. First you need to get access to the default template file that is used to generate the classes. If you look at the MSDN documentation on T4, the topic title is “Generating Artifacts by Using Text Templates.” This knowledge helps make context menu option, Add New Artifact Generation Item...more obvious as the item to choose. Microsoft will change this post-Beta to a more clear description.

When you select this option, the wizard will open the Add Item dialog with the ADO.NET EntityObject Generator selected giving it a default name with the “tt” extension. Currently there is only one template available, but look for more templates to show up in the future iterations of Visual Studio 2010.

You’ll see the new template file in the Solution Explorer as shown inFigure 2. Additionally, notice that there is no longer a code file attached to the edmx file. Since the template is now responsible for generating the classes, the class file is attached to the template file.

 Click for a larger version of this image.

Figure 2: This highlighted T4 template controls the code generation for the BikeRides.edmx model.

 

If you select the model in Solution Explorer, you’ll see in its property window that the Custom Tool property is now empty. The default generator, EntityModelCodeGenerator, will no longer be used. If you want to revert back to the default, you can just re-enter the default value and EF will take care of the rest.

Now that you have the template file accessible you can begin modifying it. Since my project is C#, the C# template was pulled in but there is also a template written in Visual Basic.

VS 2010 doesn’t have a built-in T4 editor, but you’ll find a number of third-party tools that make editing the template file easier. The T4 code listings that follow are formatted using tangible’s T4 Editor, which I have installed. See the Resources sidebar for info on T4 editors.

A T4 template has two types of content. The first is straight text, which is written directly to the target file. The second is executable code, called a directive, which is embedded in a pair of angle brackets with hash signs.

The directive will process some logic and write out the text that is the result of that logic. If you are used to working in HTML markup, this may look familiar.

This code snippet shows a directive that calls a method defined later in the T4 template.

># BeginRegion("Entities"); #>

This directive outputs a starting region tag in the generated code.

#region Entities

It might be helpful to compare the generated code file with the template to get an idea of how the template is built.

Let’s focus on the template section that generates a BikeRoute class and one of its properties, RouteName, shown in Listing 1.

The snippet below shows the template code that iterates through each entity in the model and writes out the class declaration.

First, you’ll see a directive with a comment in it that begins to look at the entities. Note that the color-coding for the T4 code is provided a Visual Studio extension by tangible Engineering called tangible T4 Editor. See the sidebar, Resources-T4, for more info.

<#
  ////////
  //////// Write EntityType classes
  ////////
  BeginRegion("Entities");
  foreach(EntityTypeWrapper entity 
          in Edm.SourceEntities
         .OrderBy(e =e.ModelName))
   {
#>

After the end of the first directive, the template writes the beginning summary tag to the class file and then uses another directive to determine what goes into the summary comments.

/// <summary>
/// <#=entity.SummaryComment#>
/// </summary>

Next, another directive looks to see if there is a LongDescription for the entity and if so, writes that out.

<#=entity.GetLongDescriptionComment

   (_regionIndentLevel)#>

 

Now some more text is written followed by the model namespace, which is determined by another directive.

"
EF4 allows developers to create classes that can be simple classes yet still take part in the Entity Framework.
"

 

[EdmEntityTypeAttribute(
   NamespaceName=
    "<#=entity.ModelNamespace#>",
   Name="<#=entity.ModelName#>")]
[Serializable()]
[DataContractAttribute(IsReference=true)]

The template continues with more code that reads the xml in the edmx file and generates all of the code necessary for the entity classes.

Customizing the classes is a matter of modifying the template. For example, by deleting the line of template code that writes out the DataContractAttribute you can eliminate the DataContractAttribute from every entity class that is created.

With this syntax, you can have enormous control over the outcome of the entity classes that you will use in your application.

&

By: Julia Lerman

Julie Lerman is a Microsoft MVP, .NET mentor and consultant who lives in the hills of Vermont. You can find Julie presenting on data access and other topics at user groups and conferences around the world. Julie blogs at thedatafarm.com/blog and is the author of the highly acclaimed Programming Entity Framework (O’Reilly Media). Follow Julie on twitter at julielermanvt.

 

 

 

 

jlerman@thedatafarm.com



Listing 1: Part of the BikeRoute class generated by the default template
[EdmEntityTypeAttribute(NamespaceName="BikeRides",
                        Name="BikeRoute")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
[KnownTypeAttribute(typeof(MountainBikeRoutes))]
public partial class BikeRoute : EntityObject
{
  [EdmScalarPropertyAttribute(EntityKeyProperty=false,
                              IsNullable=false)]
  [DataMemberAttribute()]
  public global::System.String RouteName
  {
    get
    {
      return _RouteName;
    }
    set
      {
        OnRouteNameChanging(value);
        ReportPropertyChanging("RouteName");
        _RouteName = StructuralObject.SetValidValue(
                     valuefalse);
        ReportPropertyChanged("RouteName");
        OnRouteNameChanged();
      }
              
    }
    private global::System.String _RouteName;
    partial void OnRouteNameChanging
     (global::System.String value);
    partial void OnRouteNameChanged(); 

 

Now some more text is written followed by the model namespace, which is determined by another directive. 

 

posted @ 2010-06-01 06:04  i'm zjz  阅读(511)  评论(0编辑  收藏  举报