At its core, the ADO.NET Entity Framework relies on an Entity Data Model. An EDM provides all the metadata the framework needs to translate LINQ queries into SQL commands and materialize objects from query results. This metadata includes a storage model (which describes a database schema), a conceptual model (which describes entities used in the application), and the mapping between the storage and conceptual models. One approach to creating an EDM is to right-click on a project, select Add New Item, and select the item template named ADO.NET Entity Data Model.
Adding this item template to a project will create an XML file with an .edmx extension. The XML contents of the .edmx fully describe the conceptual and storage models, as well as the mapping between the two models. The Entity Designer also stores layout information in the .edmx file related to the graphical display of the models on the design surface in Visual Studio. When adding a new EDM item, you can choose to start with an empty model, or generate a model by selecting tables, views, and stored procedures in an existing database.
Regardless of how the EDM comes into existence, a developer can use the Entity Designer to construct a conceptual model of their domain. The conceptual model includes definitions for entities, entity properties, and the relationships between entities. For example, in building a conceptual model of an application to work with movie reviews, you might define Movie and Review entities and include a one to many relationship between the two entities.
The Entity Designer saves this conceptual model into the .edmx file using an XML derivative known as conceptual schema definition language (CSDL). While tools like the Entity Designer can readily consume CDSL, the developer who wants to work with the conceptual model inside an application needs CLR type definitions – not XML. In this example, we’d expect to work with a class named Movie and a class named Review.
Fortunately, the Entity Designer includes tools to generate code from an EDM. The default code generator is the EntityModelCodeGenerator, and it can transform CSDL into C# or Visual Basic code (creating the object layer, in Entity Framework parlance). You’ll see this default generator as the custom tool for an .edmx file by default. Whenever you save an .edmx file, the generator will execute and generate the object layer into a .cs or .vb file behind the .edmx file. This is similar to how T4 templates work, but we are not using templates yet.
If we open the generated Movies.Designer.cs file, we’ll find the following class definition for a Movie (some code omitted for brevity).
- [EdmEntityTypeAttribute(NamespaceName="MovieReviewsModel", Name="Movie")]
- [Serializable()]
- [DataContractAttribute(IsReference=true)]
- public partial class Movie : EntityObject
- {
- [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
- [DataMemberAttribute()]
- public int ID
- {
- get
- {
- return _ID;
- }
- set
- {
- if (_ID != value)
- {
- OnIDChanging(value);
- ReportPropertyChanging("ID");
- _ID = StructuralObject.SetValidValue(value);
- ReportPropertyChanged("ID");
- OnIDChanged();
- }
- }
- }
- ...
- }
This is where the Entity Framework faces a dilemma. Different developers apply different constraints and requirements on the entity objects they use. Some developers need entities to derive from a common base class in their application domain. Other developers need entities supporting serialization, change tracking, and change notification. Still other developers demand support for POCOs (plain old CLR objects) – persistence ignorant classes with no ties to any 3rd party framework infrastructure.
Instead of trying to anticipate and fulfill every possible scenario and requirement, the Entity Framework team decided to use T4 templates as an extensibility mechanism. T4 templates allow developers to customize or completely replace the code generation strategy. (重点在这里)
In addition to using the EntityModelCodeGenreator, the Entity Framework provides T4 templates for generating the object layer. There are two templates provided with Visual Studio 2010, and additional templates are available for download. To use one of these templates, right-click on the design surface of an .edmx file and select the “Add Code Generation Item” command.
Selecting the command will launch a dialog box allowing you to select one of the installed code-generation items, or to search for new items online (a topic we’ll revisit later). The two templates installed with Visual Studio 2010 include the “ADO.NET EntityObject Generator”, and the “ADO.NET Self-Tracking Entity Generator”. We’ll look at the EntityObject Generator first.
The EntityObject Generator is a T4 template that generates the same default code as the EntityModelCodeGenerator. However, the EntityObject Generator comes in the form of an editable T4 template. The template will become a part of your project, and you can open the template to make modifications. The generated object layer will reflect these modifications. Let’s see how the process works.
In the Add New Item dialog, you can enter a name for the EntityObject Generator. Like all T4 templates, the new item will have a .tt extension. If you look in the Solution Explorer window after you enter a name and click the Add button, you’ll find the .tt file added to the project. The custom tool for the .tt file will be the same TextTemplatingFileGenerator we saw earlier with our simple template. Just as with the simple template, the generator will transform this template into a code file. In the following screen shot, we’ve named the new item Movies.tt.
The file containing the template output is Movies.cs. As we mentioned earlier, this file will contain the same code we would see generated by the EntityModelCodeGenerator. Before we look at the template creating this code, let’s look at what is different about our .edmx file.
If you examine the properties of the conceptual model you’ll see the Code Generation Strategy value is set to “None”. You can examine the property by double-clicking the .edmx file to open the file in the designer, then right-clicking in the white space of the designer and selecting Properties. A value of “None” means the EntityModelCodeGenerator will no longer create an object layer in the Movies.Designer.cs file. The file still exists, but if you open the file you’ll only find a comment telling you that default code generation is disabled. If you want to return to using the default code generation strategy, change the value to “Default”.
It’s important to understand that even though Code Generation Strategy is set to “None” we are still generating code, and the EDM is still the authoritative source of the conceptual model. Looking inside the EntityObject generator template, you’ll find the following lines of code near the top of the template.
- UserSettings userSettings =
- new UserSettings
- {
- SourceCsdlPath = @"Movies.edmx",
- ReferenceCsdlPaths = new string[] {},
- FullyQualifySystemTypes = true,
- CreateContextAddToMethods = true,
- CamelCaseFields = false,
- };
Notice the SourceCsdlPath property of the UserSettings. The property holds a relative path to the .edmx file the template will use to generate code. Thus, the generated code will continue to reflect changes made in the Entity Designer.
Shortly after the release of EF 4.0 and Visual Studio 2010, developers from inside and outside of Microsoft began to provide additional T4 templates for use with the Entity Framework. You can install these additional templates from the Visual Studio Gallery.
In the following screenshot, we’ve gone to the Visual Studio Extension Manager, selected the Online Gallery, and searched for the term “entity”. The top result in this search is the “ADO.NET C# POCO Entity Generator”. POCO stands for “plain old CLR object” and implies an object with no ties to data access APIs or 3rd party infrastructure. The EF team created this template to provide support for generating simple POCO class definitions from an EDM. Clicking Download will automatically download and install the template.
Once the extension is installed, you’ll be able to use the POCO template as easily as the built-in templates. Right-click on the Entity Designer to add a new code generation item, and you’ll be able to select the template from the list of available templates.