Introduction

In part one of this series, we looked at our motivation for the series, and we discussed the file differences between EDMX & csdl, ssdl & msl files. In part two, we will discuss generating a model from a database, and generating code from a model.

Model Generation

In Visual Studio, there is a wizard that walks you through the process of connecting to a database, and generating an Entity Data Model from it. The wizard allows you to select the tables, views & stored procedures to include in your EDM model. Similar functionality is available from the command-line:

edmgen.exe /mode:FullGeneration /connectionstring:"Data Source=%ProgramFiles%\Microsoft SQL Server Compact Edition\v3.5\Samples\Northwind.sdf" /provider:System.Data.SqlServerCe.3.5 /project:SqlCENorthwind

The example above doesn’t allow you to select the database objects in the model, and it also does a bit more than generating the model, as it also generates code & views. We’ll describe code generation in more detail below, and we’ll describe view generation in part 3 of this series. For now though, we’ll take a quick look at the APIs to generate a model from a database. In Listing 2, we call the EntityStoreSchemaGenerator and the EntityModelSchemaGenerator. These classes are defined in the System.Data.Entity.Design namespace and are packaged in an assembly of the same name.

The code below generates the ssdl from a database, and then generates the csdl & msl to complete the EDM model. Finally it writes this data into an EDMX file.

   private static void ModelGen(
      string connectionString, string provider, string modelName)
   {
        IList<EdmSchemaError> ssdlErrors = null;
        IList<EdmSchemaError> csdlAndMslErrors = null;

            // generate the SSDL
            string ssdlNamespace = modelName + "Model.Store";
            EntityStoreSchemaGenerator essg =
                new EntityStoreSchemaGenerator(
                    provider, connectionString, ssdlNamespace);
            ssdlErrors = essg.GenerateStoreMetadata();

            // write out errors
            if ((ssdlErrors != null && ssdlErrors.Count > 0))
            {
                System.Console.WriteLine("Errors occurred during generation:");
                WriteErrors(ssdlErrors);
                return;
            }

            // write the SSDL to a string
            StringWriter ssdl = new StringWriter();
            XmlWriter ssdlxw = XmlWriter.Create(ssdl);
            essg.WriteStoreSchema(ssdlxw);
            ssdlxw.Flush();

            // generate the CSDL
            string csdlNamespace = modelName + "Model";
            string csdlEntityContainerName = modelName + "Entities";
            EntityModelSchemaGenerator emsg =
                new EntityModelSchemaGenerator(
                    essg.EntityContainer, csdlNamespace, csdlEntityContainerName);
            csdlAndMslErrors = emsg.GenerateMetadata();

            // write out errors
            if (csdlAndMslErrors != null && csdlAndMslErrors.Count > 0)
            {
                System.Console.WriteLine("Errors occurred during generation:");
                WriteErrors(csdlAndMslErrors);
                return;
            }

            // write CSDL to a string
            StringWriter csdl = new StringWriter();
            XmlWriter csdlxw = XmlWriter.Create(csdl);
            emsg.WriteModelSchema(csdlxw);
            csdlxw.Flush();

            // write MSL to a string
            StringWriter msl = new StringWriter();
            XmlWriter mslxw = XmlWriter.Create(msl);
            emsg.WriteStorageMapping(mslxw);
            mslxw.Flush();

            // write csdl, ssdl & msl to the EDMX file
            ToEdmx(
                csdl.ToString(), ssdl.ToString(), msl.ToString(), new FileInfo(
                    modelName + ".edmx"));
        }

Listing 2. Code example generating a model from a database. Full code can be downloaded here.

Code Generation

“Code Generation”, in the context of the EDM, refers to the process where we generate classes from the entities & associations defined in your EDMX file. These classes are what give you programmatic access to your data. In Visual Studio, we generate code through a Visual Studio “Single File Generator”. The Single File Generator (SFG) is kicked off whenever the EDMX file is saved, and this causes the “.Designer.cs” (or “.Designer.vb”) code-behind file to be updated. You can also launch the SFG by right-clicking an EDMX file in solution explorer, and choose the “Run Custom Tool” context menu.

To generate code from the command-line, you would use the following command:

edmGen.exe /mode:EntityClassGeneration /incsdl:SqlCENorthwind.csdl /language:CSharp /outobjectlayer:SqlCENorthwind.cs

In Listing 3, we show the code to generate code from an EDMX. This uses the EntityClassGenerator class.

 

private static void CodeGen(FileInfo edmxFile, LanguageOption languageOption)
{
    XElement c = GetCsdlFromEdmx(XDocument.Load(edmxFile.FullName));

   
// generate code
   
StringWriter sw = new
StringWriter();
    EntityClassGenerator codeGen =
new
EntityClassGenerator(languageOption);
    IList<EdmSchemaError> errors = codeGen.GenerateCode(c.CreateReader(), sw);

   
// write out code-file
   
string outputFileName = GetFileNameWithNewExtension(edmxFile,
                GetFileExtensionForLanguageOption(languageOption));

   
File.WriteAllText(outputFileName, sw.ToString());

   
// output errors
    WriteErrors(errors);

}   

Listing 3. Code example to run code-gen on an EDMX file. Full code can be downloaded here.

Coming Up Next

In part three of this four-part series, we will look at the validation and view generation APIs available to validate EDM models, and generate ESql views for models.

Mike Kaufman
Software Design Engineer