I’ve had this article pending for a while; numerous folks wanted more information on this topic and I finally got some this weekend and wrote it up for your reading pleasure.
The ADO.NET Entity Designer stores all its information in the EDMX file which merely encapsulates the EF metadata artifacts (CSDL/MSL/SSDL content) along with a bunch of designer data in a single file. I’ve described the structure of the EDMX file in a previous post.
The ADO.NET Entity Designer generates data classes from the CSDL portion of the EDMX file. We extract the CSDL from the EDMX in a manner similar to what I’ve described in this post . Assuming there are no errors during code generation, these classes are immediately visible in the project and are ready for consumption in the project. There are 2 parts to how the designer generates code:
1. We register a generator (called EntityModelCodeGenerator) with Visual Studio using a standard extensibility mechanism called SingleFileGenerator. Visual Studio calls EntityModelCodeGenerator as necessary when the content of the EDMX file changes.
2. The EntityModelCodeGenerator in turn extracts the CSDL from the EDMX and calls public code generation APIs in the EntityClassGenerator class (in the System.Data.Entity.Design namespace) to generate code in the required project language.
If you select any EDMX file in Solution Explorer and look at the Visual Studio property window, you’ll see that it’s “Custom Tool” property is set to EntityModelCodeGenerator. This tells Visual Studio to call our generator when the content of the EDMX file changes.
A SingleFileGenerator is basically a COM component that implements the IVsSingleFileGenerator interface. Visual Studio 2008 has a number of SingleFileGenerators: MSDataSetGenerator, ResXFileCodeGenerator , SettingsSingleFileGenerator, etc are all SingleFileGenerators. Linq to SQL uses a SingleFileGenerator too (called MSLinqToSQLGenerator).
Before the mention of COM scares you away, there’s tons of great information on SingleFileGenerators and Visual Studio extensibility on MSDN and the Visual Studio 2008 SDK has an excellent SingleFileGenerator sample that you can use as a starting point for your own. For most purposes, you can copy/paste the sample in the VS 2008 SDK, do what you need in the GenerateCode() override, register the SIngleFileGenerator and you are pretty much done (trust me!).
While I won’t dwell on the finer points of VS extensibility and SingleFileGenerators, I will note that the contract for a SingleFileGenerator is pretty straight forward. After it is registered correctly with Visual Studio, every SingleFileGenerator is required to override the GenerateCode() method whose signature looks as follows from the VS 2008 SDK sample:
protected override byte GenerateCode(string inputFileContent)
The overall flow is as follows:
· Visual Studio calls your GenerateCode override with the file buffer contents when needed (e.g. when buffer contents change, file save, project build, active window changes, etc).
· In your override, you look at the file buffer contents, do whatever processing you need and give a byte array with the generated code back to Visual Studio.
· Visual Studio takes your byte array and puts it into a “code behind” file in the project. For example, the Model1.edmx has its generated code in Model1.Designer.cs or Model1.Designer.vb depending on the project language.
A SingleFileGenerator has access to the Visual Studio error list and can report errors/warnings. Visual Studio manages double-click behavior for errors/warnings reported by a SingleFileGenerator by taking you to the offending line/column in the correct file. A SingleFileGenerator also has access to the project system in case you want to, say; traverse the list of project items in a particular folder, etc. Visual Studio manages the lifetime of the “code behind” file and is also responsible for additional project housekeeping things like Source Control interaction.
Since the ADO.NET Entity Designer leverages the SingleFileGenerator extensibility point, you can replace our SingleFileGenerator with one you create by simply setting the “Custom Tool” property of the EDMX file to a customized generator of your choosing.
I’ll explore scenarios where this is interesting in a separate blog post.
Program Manager, ADO.NET