Partager via


EDM Tools | Options (Part 3 of 4)

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

Comments

  • Anonymous
    June 26, 2008
    PingBack from http://blogs.msdn.com/adonet/archive/2008/06/20/edm-tools-options-part-2-of-4.aspx

  • Anonymous
    June 26, 2008
    I'd like to make a small suggestion, that the validation be put inside a unit test.  That way, every time you run your automated build, you'll get immediate feedback on the validity of your model. Even better, part of a full continuous integration process, so the entire team knows if someone broke the model. I'm not picky, so you could do all of this with MSTest and Team Build 2008. View generation could also be part of your automated build, as it's very easy to call an executable from both major build technologies.  That way, whatever gets deployed has the views ready to go.  No human intervention needed.  Whether or not you'd want to commit the generated views back to source control is debatable.

  • Anonymous
    June 30, 2008
    Hello, guys! When are you planning to release ADO.NET EF and Tools? Tnx

  • Anonymous
    July 14, 2008
    Introduction In parts one , two and three of this four-part series, we discussed the file differences

  • Anonymous
    June 10, 2009
    Last summer, the senior developer on the Entity Designer team (Mike Kaufman) wrote a series of blog posts

  • Anonymous
    February 09, 2010
    Hi, We've tried to implement the View generation example but can't compile the end result. The compiler complains that a 'construct is too complex to compile'. CodeRush even crashes when trying to load the code in Visual Studio 2008. Regards Paul Sinnema

  • Anonymous
    February 19, 2014
    Hey Paul Sinnema, it would appear from your post that your datamodel is "complex" which to me is:

  1. it's not normalized
  2. try to get it to 3rd Normal form
  3. entity framework works well with a properly modeled database. What it seems to me is that people interested in a database to store information have no concept, especially business leaders, of a properly normalized database.  So I would like to say to Paul that I'm not criticizing his model or his database as obviously he can't post his schema here but what I read and infer is that it needs a look at from a database administrator and sql developer type of background to normalize it.