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.aspxAnonymous
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? TnxAnonymous
July 14, 2008
Introduction In parts one , two and three of this four-part series, we discussed the file differencesAnonymous
June 10, 2009
Last summer, the senior developer on the Entity Designer team (Mike Kaufman) wrote a series of blog postsAnonymous
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 SinnemaAnonymous
February 19, 2014
Hey Paul Sinnema, it would appear from your post that your datamodel is "complex" which to me is:
- it's not normalized
- try to get it to 3rd Normal form
- 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.