software development

NAnt and Processing EDMX Files

I have been playing around with the new data access layer, the Entity Data Model (EDM), from Microsoft. However, I quickly learned that the EDMX files that Visual Studio creates for you when you create a data model are unique to Visual Studio. In fact, an EDM is made up of three files that are known as metadata artifacts:

  • Conceptual Model – CSDL
  • Storage Model – SSDL
  • Mappings Model – MSL


Visual Studio so kindly embeds these files for you in your assembly when you build your project. However, what about NAnt? As it turns out the metadata artifacts are all stored in the single EDMX file that Visual Studio creates, you just have to pull them out. In order to successfully build a library that uses the new EDM I did just that with an in-line NAnt script. Here you go:


<!-- copy dependencies into the build directory -->
<copy todir="${build}" flatten="true">
  <fileset basedir="${lib.dir}">
    <patternset refid="lib.default" />
  </fileset>
</copy>

<!-- create the resource files -->
<resgen todir="${res}" failonerror="false">
  <resources prefix="${project::get-name()}.${res}">
    <include name="${res}/*.resx"/>
  </resources>
</resgen>

<!-- create the edm metadata resources -->
<property name="edmxfile" value="${path::get-full-path(src+'/Directory.edmx')}"/>
<property name="edmoutpfx" value="${src}."/>
<property name="edmoutdir" value="${path::get-full-path(src)}"/>

<script language="C#">
  <references>
    <patternset refid="lib.dotnet.framework" />
  </references>
  <imports>
    <import namespace="System.Xml.Linq"/>
  </imports>
  <code>
  < !&#91;CDATA&#91;
    public static void ScriptMain(Project project)
    {
    string p = project.Properties&#91;"edmxfile"&#93;;

    // Define the namespaces.
    XNamespace edmxns = "http://schemas.microsoft.com/ado/2007/06/edmx";
    XNamespace ssdlns = "http://schemas.microsoft.com/ado/2006/04/edm/ssdl";
    XNamespace csdlns = "http://schemas.microsoft.com/ado/2006/04/edm";
    XNamespace mslns = "urn:schemas-microsoft-com:windows:storage:mapping:CS";

    // Load the EDMX document.
    XDocument doc = XDocument.Load(p);

    // Get the common nodes.
    XElement enode = doc.Element(edmxns + "Edmx");
    XElement rnode = enode.Element(edmxns + "Runtime");

    // Get the three EDM nodes.
    XElement ssdlnode = rnode.Element(edmxns + "StorageModels");
    XElement csdlnode = rnode.Element(edmxns + "ConceptualModels");
    XElement mslnode = rnode.Element(edmxns + "Mappings");

    // Get the CSDL, SSDL, and MSL content nodes.
    XElement ssdlcon = ssdlnode.Element(ssdlns + "Schema");
    XElement csdlcon = csdlnode.Element(csdlns + "Schema");
    XElement mslcon = mslnode.Element(mslns + "Mapping");

    // Write the content to files.
    string fnwe = System.IO.Path.GetFileNameWithoutExtension(p);
    ssdlcon.Save(string.Format(
      "{0}/{1}{2}.ssdl",
      project.Properties&#91;"edmoutdir"&#93;,
      project.Properties&#91;"edmoutpfx"&#93;,
      fnwe));
    csdlcon.Save(string.Format(
      "{0}/{1}{2}.csdl",
      project.Properties&#91;"edmoutdir"&#93;,
      project.Properties&#91;"edmoutpfx"&#93;,
      fnwe));
    mslcon.Save(string.Format(
      "{0}/{1}{2}.msl",
      project.Properties&#91;"edmoutdir"&#93;,
      project.Properties&#91;"edmoutpfx"&#93;,
      fnwe));
    }
    &#93;&#93;>
  </code>
</script>

<!-- compile the main assembly -->
<csc target="library"
      output="${build}/${proj.name.unix}.dll"
      doc="${build}/${proj.name.unix}.xml"
      warninglevel="0"
      debug="PdbOnly"
      define="CODE_ANALYSIS"
      noconfig="true"
      optimize="true">
  <sources>
      <patternset refid="src.generated" />
      <include name="${src}/**/*.cs" />
      <include name="${res}/**/*.cs" />
    </sources>
  <references>
    <include name="${build}/*.dll"/>
    <exclude name="${build}/${proj.name.unix}.dll"/>
    <patternset refid="lib.dotnet.framework" />
  </references>
  <resources>
    <include name="${res}/*.resources"/>
    <include name="${src}/*.ssdl"/>
    <include name="${src}/*.csdl"/>
    <include name="${src}/*.msl"/>
  </resources>
  <nowarn>
    <!-- http://msdn.microsoft.com/en-us/library/2h4x8b08(VS.80).aspx -->
    <warning number="1701" />
    <!-- http://msdn.microsoft.com/en-us/library/wc57zasf(VS.80).aspx -->
    <warning number="1702" />
  </nowarn>
</csc>

As you can see, the in-line script pulls out the metadata artifact content and then embeds the resulting CSDL, SSDL, and MSL file as resources in the compiled assembly. Easy as pie!

Advertisements

5 thoughts on “NAnt and Processing EDMX Files

  1. Would be nice if you could potentially release your entire build script that we could review… the script itself doesn’t quite give you everything you need, from what I can figure out… then again, I’m a noob with nAnt.

    Thx.

  2. I don’t need this, as after about two days, I found out where it goes… I do think, however, that it would be helpful if you would put a sample working project out there so that others that hit this post can understand what to do, in detail… although a pic is worth 1,000 words, an example is worth a million at times ;)

  3. I going crazy here. I am trying to compile a project with edmx file. Compiles fine with visual studio, but when trying to compile with NANT I am getting errors on designer.cs file..
    like
    rror CS0234: The type or namespace name ‘Objects’ does no
    t exist in the namespace ‘System.Data’ (are you missing an assembly reference?)
    The type or namespace name ‘EntityObject’ could not be found (are you missing a using directive or an assembly reference?)
    error CS0246: The type or namespace name ‘EntityObject’ could not be found (are you missing a using directive or an assembly reference?)

    I am targetting .net 4.0 and all those dlls exist. This i could confirm because, if i include them explicitly in the nant build file, it complains that the specified assemblies are already imported.
    I am not sure why I am getting these errors.
    Please help.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s