EDM Tools | Options (Part 1 of 4)

Introduction

The Entity Data Model (EDM) Tools team has done a lot of work to enable a productive developer experience using the Microsoft Entity Framework. Model generation, model validation, and code generation are all plugged into the Visual Studio (VS) environment for a seamless user experience. Model generation is accomplished through a Visual Studio wizard, while model validation and code generation are behind-the-scenes operations that users generally need not think about. Consequently, you may not realize that the tooling functionality integrated into Visual Studio is also available from the command-line (via EdmGen.exe), and via programmatic APIs defined in the System.Data.Entity.Design namespace and assembly. Access to this functionality can be very useful. For example, you can hook code-generation and validation into your automated build. Or, you can write your own tools, like MSBuild tasks, to generate code or validate models.

This is the first in a series of four posts that look at tooling options for the EDM. In this series, we review some of the EDM tooling processes that are integrated into Visual Studio, and discusses alternatives for running these outside of VS - either from the command-line or from your own program. The motivating example we use is building a simple replacement for the .Net Framework tool EdmGen.exe. The approach we follow is to first look at a piece of functionality integrated into the Visual Studio experience. Then, we look at how it is available via the EdmGen.exe tool, and then we’ll look at the public APIs available in the .Net Framework.

In this first post, we discuss the different file formats between the Visual Studio tools & the Entity Framework APIs in the .Net Framework. In the second part, we will review how to generate models from a database, and how to generate code from a model. In the third part, we look at the validation of models & mappings. The final part in this series will tie all of the previous examples together into a command-line tool that understands how to read and write the EDMX file formats.

Full source-code for the full command-line tool is available at https://code.msdn.microsoft.com/EdmGen2. This contains code for all examples in this series.

EDMX files vs. CSDL, SSDL and MSL files

Before we discuss the tooling tasks outside of VS, we first need to address a slight difference in file formats. In the beginning, there was only an Entity Framework runtime, and the runtime operated on three different files: one for the “conceptual model” (the .csdl file), another for the “storage model” (the .ssdl file), and a third for the “mapping” (the .msl file). Internally, the Data Programmability team refers to a set of these files as “c/m/s files”. The EDM Tools Team made a decision simplify the VS experience by aggregating the c/m/s files into a single .edmx file. The unfortunate state of affairs for V1 is that EdmGen.exe and the Entity Framework APIs that ship in the .Net runtime can’t read EDMX files.

Breaking Down an EDMX File

The first bit of Code that we we’ll show you is how to extract an EDMX file into the “c/m/s” parts. This is actually quite simple, since the EDMX file embeds the csdl, ssdl & msl. In the code below, we use Linq To Xml to extract the appropriate data from the EDMX, and write out separate files for the csdl, ssdl & msl. To do the inverse (ie, combine c/m/s files into an EDMX), see the full code listing at the MSDN Code Gallery.

      private static void FromEdmx(FileInfo edmxFile)
     {
            XDocument xdoc = XDocument.Load(edmxFile.FullName);

            // select the csdl element, and write it out
            XElement csdl = GetCsdlFromEdmx(xdoc);
            string csdlFileName = GetFileNameWithNewExtension(edmxFile, ".csdl");
            File.WriteAllText(csdlFileName, csdl.ToString());

            // select the ssdl element and write it out
            XElement ssdl = GetSsdlFromEdmx(xdoc);
            string ssdlFileName = GetFileNameWithNewExtension(edmxFile, ".ssdl");
            File.WriteAllText(ssdlFileName, ssdl.ToString());

            // select the msl element and write it out
            XElement msl = GetMslFromEdmx(xdoc);
            string mslFileName = GetFileNameWithNewExtension(edmxFile, ".msl");
            File.WriteAllText(mslFileName, msl.ToString());
     }

     private static XElement GetCsdlFromEdmx(XDocument xdoc)
     {
            return (from item in xdoc.Descendants(
                        XName.Get("Schema", csdlNamespace)) select item).First();
     }

     private static XElement GetSsdlFromEdmx(XDocument xdoc)
     {
            return (from item in xdoc.Descendants(
                        XName.Get("Schema", ssdlNamespace)) select item).First();
     }

     private static XElement GetMslFromEdmx(XDocument xdoc)
     {
            return (from item in xdoc.Descendants(
                        XName.Get("Mapping", mslNamespace)) select item).First();
     }

Listing 1. Code to extract CSDL, SSDL & MSL sections from an edmx into files. Full code can be downloaded.

Coming Up Next

In part two of this four-part series, we will review the command-line & .NET APIs around EDM model and code generation.

Mike Kaufman
Software Design Engineer, ADO.NET Tools