Introduction

In parts one and two of this four-part series, we discussed the file differences between EDMX & csdl, ssdl & msl files, and we looked at the model & code generation APIs available in the .Net Runtime. In Part three, we discuss validation of EDM models, and we look at view generation for EDM models.

Model Validation

The Visual Studio experience validates your EDMX models during a build, whenever an EDMX file is saved, and whenever a user selects the “Validate” context menu in the EDM designer. To validate a model from the command-line, you can execute the following command:

edmGen.exe /mode:ValidateArtifacts /incsdl:SqlCENorthwind.csdl /inssdl:SqlCENorthwind.ssdl /inmsl:SqlCENorthwind.msl

The code to programmatically validate a model defined in an EDMX file is shown in Listing 1. Here, we load the ssdl, csdl & msl into EdmItemCollection instances. The process of loading these returns a list of errors that we can output. We then compile the mappings, which does a semantic validation to ensure that the mappings are correct for the EDM.

To programmatically validate a model, you can do the following:

private static void Validate(
            FileInfo edmxFile)
        {
            XDocument doc = XDocument.Load(edmxFile.FullName);
            XElement c = GetCsdlFromEdmx(doc);
            XElement s = GetSsdlFromEdmx(doc);
            XElement m = GetMslFromEdmx(doc);

            // load the csdl
            XmlReader[] cReaders = { c.CreateReader() };
            IList<EdmSchemaError> cErrors = null;
            EdmItemCollection edmItemCollection = 
                MetadataItemCollectionFactory.CreateEdmItemCollection(cReaders, out cErrors);

            // load the ssdl 
            XmlReader[] sReaders = { s.CreateReader() };
            IList<EdmSchemaError> sErrors = null;
            StoreItemCollection storeItemCollection = 
                MetadataItemCollectionFactory.CreateStoreItemCollection(sReaders, out sErrors);

            // load the msl
            XmlReader[] mReaders = { m.CreateReader() };
            IList<EdmSchemaError> mErrors = null;
            StorageMappingItemCollection mappingItemCollection = 
                MetadataItemCollectionFactory.CreateStorageMappingItemCollection(
                edmItemCollection, storeItemCollection, mReaders, out mErrors);

            // validate the mappings
            IList<EdmSchemaError> viewGenerationErrors = null;
            viewGenerationErrors = EntityViewGenerator.Validate(mappingItemCollection);

            // write errors
            WriteErrors(cErrors);
            WriteErrors(sErrors);
            WriteErrors(mErrors);
            WriteErrors(viewGenerationErrors);
        }

Listing 1. Code example to validate an EDMX file. Full code can be downloaded here.

Generating Views

The Entity Framework runtime reasons about your data model via ESql Views. The runtime will generate and cache views if they aren’t included in your assembly, so there is no need to pre-generate the views. However, view-generation can be expensive. Pre-generating views and compiling them into your assembly may eliminate some of your application’s start-up costs. Inside of Visual Studio, we don’t do anything with the pre-generating views, but views can be generated using EdmGen.exe with the following command:

edmGen.exe /mode:ViewGeneration /incsdl:SqlCENorthwind.csdl /language:CSharp /outviews:views.cs /inmsl:SqlCENorthwind.msl /inssdl:SqlCENorthwind.ssdl

The views are output as ESql queries in a C# or VB file. After running the above example, the file views.cs will contain the views, and views.cs will need to be compiled into your assembly.

The code in Listing 2 below illustrates programmatically generating views given an EDMX file. You’ll note that the code below is very similar to the validation code in Listing 1. This is because the data structures built during validation are needed to perform view-compilation. In fact, the only difference between the validation and view generation is that view generation will output the views to a file.

private static void ValidateAndGenerateViews(
            FileInfo edmxFile, LanguageOption languageOption)
        {
            XDocument doc = XDocument.Load(edmxFile.FullName);
            XElement c = GetCsdlFromEdmx(doc);
            XElement s = GetSsdlFromEdmx(doc);
            XElement m = GetMslFromEdmx(doc);

            // load the csdl
            XmlReader[] cReaders = { c.CreateReader() };
            IList<EdmSchemaError> cErrors = null;
            EdmItemCollection edmItemCollection = 
                MetadataItemCollectionFactory.CreateEdmItemCollection(cReaders, out cErrors);

            // load the ssdl 
            XmlReader[] sReaders = { s.CreateReader() };
            IList<EdmSchemaError> sErrors = null;
            StoreItemCollection storeItemCollection = 
                MetadataItemCollectionFactory.CreateStoreItemCollection(sReaders, out sErrors);

            // load the msl
            XmlReader[] mReaders = { m.CreateReader() };
            IList<EdmSchemaError> mErrors = null;
            StorageMappingItemCollection mappingItemCollection = 
                MetadataItemCollectionFactory.CreateStorageMappingItemCollection(
                edmItemCollection, storeItemCollection, mReaders, out mErrors);

            // generate views & write them out to a file
            IList<EdmSchemaError> viewGenerationErrors = null;
            string outputFile =
                GetFileNameWithNewExtension(edmxFile, ".GeneratedViews" +
                    GetFileExtensionForLanguageOption(languageOption));
            EntityViewGenerator evg = new EntityViewGenerator(languageOption);
            viewGenerationErrors =
                evg.GenerateViews(mappingItemCollection, outputFile);

            // write errors
            WriteErrors(cErrors);
            WriteErrors(sErrors);
            WriteErrors(mErrors);
            WriteErrors(viewGenerationErrors);
        }

Listing 2. Code example showing programmatic view generation. Full code can be downloaded here.

Coming Up Next

In the final installment of this four-part series, we combine the code we’ve written into a new command-line tool called EdmGen2.exe. This is similar in functionality to EdmGen.exe, but understands how to read & write EDMX files.

Mike Kaufman
Software Design Engineer