<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Data and Modeling Customer Advisory Team</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/dmcat/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/dmcat/feed.xml</link>
    <description />
    <lastBuildDate>Wed, 17 Apr 2019 03:20:26 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Epicor Visual Studio 2010 Entity Framework Case Study Posted</title>
      <link>https://docs.microsoft.com/archive/blogs/dmcat/epicor-visual-studio-2010-entity-framework-case-study-posted</link>
      <pubDate>Mon, 03 May 2010 14:39:00 GMT</pubDate>
      <dc:creator><![CDATA[dkaufman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmcat/2010/05/03/epicor-visual-studio-2010-entity-framework-case-study-posted/</guid>
      <description><![CDATA[Check out the Epicor Case Study that was recently published by one of our partners.&nbsp; Epicor is...]]></description>
      <content:encoded><![CDATA[<p>Check out the <a href="https://www.microsoft.com/casestudies/Case_Study_Detail.aspx?CaseStudyID=4000006887">Epicor Case Study</a> that was recently published by one of our partners.&nbsp; <a href="https://www.epicor.com">Epicor</a> is a global software company that creates enterprise resource planning (ERP) solutions for manufacturing firms and other customers.</p>
<p>They have been able to leverage <a href="https://msdn.microsoft.com/en-us/vstudio/default.aspx">Visual Studio 2010</a> and <a href="https://msdn.microsoft.com/en-us/data/aa937723.aspx">ADO.NET Entity Framework 4</a> to ease development and reduce SQL Server requests by 90 percent. Also, Epicor has a very large data model which the new version of Entity Framework was able to support.</p>
<p>An excerpt from the case study:</p>
<blockquote>
<p><strong><em>Because the ADO.NET Entity Framework 4 can support large data model sizes, Epicor could use the technology to create Epicor 9.05. &ldquo;The earlier version of the Entity Framework did not handle our data model size very well, and we experienced delays in testing,&rdquo; says Johnson. &ldquo;Those problems have all been solved with the ADO.NET Entity Framework 4.&rdquo;</em></strong></p>
</blockquote>]]></content:encoded>
    </item>
    <item>
      <title>Profiling Entity Framework using the Visual Studio 2010 Profiler</title>
      <link>https://docs.microsoft.com/archive/blogs/dmcat/profiling-entity-framework-using-the-visual-studio-2010-profiler</link>
      <pubDate>Fri, 30 Apr 2010 10:36:00 GMT</pubDate>
      <dc:creator><![CDATA[dkaufman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmcat/2010/04/30/profiling-entity-framework-using-the-visual-studio-2010-profiler/</guid>
      <description><![CDATA[A previous post discussed potential issues with Compiled Query recompiles. The cause of the...]]></description>
      <content:encoded><![CDATA[<P>A <A href="https://blogs.msdn.com/dmcat/archive/2010/03/08/potential-performance-issues-with-compiled-linq-query-re-compiles.aspx" mce_href="https://blogs.msdn.com/dmcat/archive/2010/03/08/potential-performance-issues-with-compiled-linq-query-re-compiles.aspx">previous post</A> discussed potential issues with Compiled Query recompiles. The cause of the recompile issues were actually uncovered by using the <A href="https://msdn.microsoft.com/en-us/library/ms182372(v=VS.100).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms182372(v=VS.100).aspx">Visual Studio 2010 Profiler</A>. This blog will cover how the Profiler can be used to discover performance issues in the Entity Framework. The sample code from the previous blog will be used as the code to be profiled.</P>
<P>Basically the code executes a compiled query against the <A href="https://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en" mce_href="https://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en">Northwind database</A> via the Entity Framework. The LINQ query (using LINQ to Entity) returns all Customers whose CustomerID starts with “C”. The code first executes the query using a <I>.Any()</I> operator to see if there will be any records returned and if so executes the query and returns a list of records which we then take the count of to make sure all of the records are inspected. The queries are executed 100 times. The sample is in a solution named EFTest which you can download <A href="https://cid-09ba3ed5e1c6b4ef.skydrive.live.com/self.aspx/Public/EF/EFAnyTest.zip" mce_href="https://cid-09ba3ed5e1c6b4ef.skydrive.live.com/self.aspx/Public/EF/EFAnyTest.zip">here</A>.</P>
<P>Executing this class returns the following results:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/TestRun_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/TestRun_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/TestRun_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=TestRun border=0 alt=TestRun src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/TestRun_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/TestRun_thumb.png" width=518 height=264 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/TestRun_thumb.png"></A> </P>
<P>Notice the first query took 1144ms which is significantly longer than the follow on queries. This is due to the warm-up that happens in the Entity Framework when an application starts. The first time an <A href="https://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext(v=VS.100).aspx" mce_href="https://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext(v=VS.100).aspx">ObjectContext</A> is used, EF opens up a connection to SQL Server and loads up the metadata for the EF model. This metadata includes the mappings between the physical and conceptual models and any pre-compiled view SQL.</P>
<P>Now let’s dig into the performance of the LINQ queries. The Visual Studio Profiler can be used to isolate potential performance issues. The Profiler can be enabled by selecting “Analyze | Launch Performance Wizard…” from the Visual Studio main menu. This launches the Performance Wizard which is shown below:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfWiz_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfWiz_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfWiz_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=PerfWiz border=0 alt=PerfWiz src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfWiz_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfWiz_thumb.png" width=473 height=407 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfWiz_thumb.png"></A>&nbsp;</P>
<P>Take the default and hit “Next”, take the default for the target application, press “Next” and then uncheck the option “Launch profiling after the wizard finishes”. Now press “Finish” which will close the wizard. </P>
<P>The Performance Explorer should be shown in Visual Studio:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfExplorer_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfExplorer_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfExplorer_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=PerfExplorer border=0 alt=PerfExplorer src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfExplorer_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfExplorer_thumb.png" width=517 height=350 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/PerfExplorer_thumb.png"></A> </P>
<P>Right click on the EFTestAny project in the Performance Explorer and select “Properties”. Select “Sampling” from the properties list and change the Sampling interval to “50000”. This will make the profile take executions samples at a faster rate which increases accuracy when profiling such a small amount of code. Click “Ok” to close the property page.</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfProp_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfProp_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfProp_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=ProfProp border=0 alt=ProfProp src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfProp_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfProp_thumb.png" width=493 height=399 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfProp_thumb.png"></A> </P>
<P>Before we start the profiling, one more task needs to be completed. Remember the first query took significantly longer than any of the subsequent queries due to opening the connection to SQL Server and EF metadata loading? We need to factor the warm-up out of the performance measurements. This can be done by making marks in the data collected by the profiler and then filtering the results on those marks. The Profiler’s API can be used to insert Data marks via code.</P>
<P>To use the Profiler API, a Profiler assembly needs to be added as a reference to the project. Right click on “References” in the Solution Explorer and pick “Add Reference…”. Use the Browse tab and select <I>c:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Performance Tools\Microsoft.VisualStudio.Profiler.dll</I></P>
<P>Next the <A href="https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.profiler.datacollection.commentmarkprofile(v=VS.100).aspx" mce_href="https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.profiler.datacollection.commentmarkprofile(v=VS.100).aspx">DataCollection.CommentMarkProfile()</A> method can be used from the code. This method adds a numeric mark and comment into the performance data being collected by the profiler. The method is passed a <I>MarkId</I> which is an integer and helps in ordering the marks and a description string. The <I>CommentMarkProfile()</I> call needs to happen after the first round of queries to get past the warm-up so that the cost can be excluded from the analysis. To do that, the following code is added after the results are printed for each pass (note the <I>if</I> statement makes sure the mark only happens after the first iteration):</P><PRE class=code><SPAN style="COLOR: blue">if </SPAN>(i == 0) <SPAN style="COLOR: green">//Mark profile data after first pass as it is warmup
</SPAN>{
    <SPAN style="COLOR: green">//Mark profiling data
    </SPAN><SPAN style="COLOR: #2b91af">DataCollection</SPAN>.CommentMarkProfile(100, <SPAN style="COLOR: #a31515">"After Warmup - Any ON compiled query"</SPAN>);
}</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>
<P>Finally, the <I>CommentMarkProfile()</I> operation is called after the for loop completes before the code pauses for a key press. The code for the second mark is shown below:</P><PRE class=code><SPAN style="COLOR: #2b91af">DataCollection</SPAN>.CommentMarkProfile(110, <SPAN style="COLOR: #a31515">"Queries Done"</SPAN>);

The complete code with the calls to the profiler API is shown below:</PRE>
<DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper>
<DIV style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum1>   1:</SPAN> <SPAN style="COLOR: black">using</SPAN> System;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum2>   2:</SPAN> <SPAN style="COLOR: black">using</SPAN> System.Collections.Generic;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum3>   3:</SPAN> <SPAN style="COLOR: black">using</SPAN> System.Linq;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum4>   4:</SPAN> <SPAN style="COLOR: black">using</SPAN> System.Text;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum5>   5:</SPAN> <SPAN style="COLOR: black">using</SPAN> System.Data.Objects;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum6>   6:</SPAN> <SPAN style="COLOR: black">using</SPAN> System.Data.Common;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum7>   7:</SPAN> <SPAN style="COLOR: black">using</SPAN> System.Data.EntityClient;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum8>   8:</SPAN> <SPAN style="COLOR: black">using</SPAN> System.Data;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum9>   9:</SPAN> <SPAN style="COLOR: black">using</SPAN> Microsoft.VisualStudio.Profiler;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum10>  10:</SPAN>&nbsp; </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum11>  11:</SPAN> <SPAN style="COLOR: black">namespace</SPAN> EFAnyTest</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum12>  12:</SPAN> {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum13>  13:</SPAN>     <SPAN style="COLOR: black">class</SPAN> Program</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum14>  14:</SPAN>     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum15>  15:</SPAN>&nbsp; </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum16>  16:</SPAN>         <SPAN style="COLOR: black">static</SPAN> Func&lt;NorthwindEntities, <SPAN style="COLOR: black">string</SPAN>, IQueryable&lt;Customer&gt;&gt; compiledCustQuery =</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum17>  17:</SPAN>            CompiledQuery.Compile((NorthwindEntities ctx, <SPAN style="COLOR: black">string</SPAN> start) =&gt;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum18>  18:</SPAN>            (from c <SPAN style="COLOR: black">in</SPAN> ctx.Customers</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum19>  19:</SPAN>             <SPAN style="COLOR: black">where</SPAN> c.CustomerID.StartsWith(start)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum20>  20:</SPAN>             select c));</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum21>  21:</SPAN>&nbsp; </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum22>  22:</SPAN>         <SPAN style="COLOR: black">static</SPAN> <SPAN style="COLOR: black">void</SPAN> Main(<SPAN style="COLOR: black">string</SPAN>[] args)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum23>  23:</SPAN>         {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum24>  24:</SPAN>             System.Diagnostics.Stopwatch sw = <SPAN style="COLOR: black">new</SPAN> System.Diagnostics.Stopwatch();</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum25>  25:</SPAN>             <SPAN style="COLOR: black">double</SPAN> totalTime = 0.0;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum26>  26:</SPAN>             <SPAN style="COLOR: black">int</SPAN> iterations = 0;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum27>  27:</SPAN>             <SPAN style="COLOR: black">int</SPAN> TEST_RUNS = 100;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum28>  28:</SPAN>&nbsp; </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum29>  29:</SPAN>             NorthwindEntities ctx = <SPAN style="COLOR: black">new</SPAN> NorthwindEntities();</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum30>  30:</SPAN>             {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum31>  31:</SPAN>                 Console.Out.WriteLine(<SPAN style="COLOR: black">"Any ON compiled query"</SPAN>);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum32>  32:</SPAN>                 <SPAN style="COLOR: black">for</SPAN> (<SPAN style="COLOR: black">int</SPAN> i = 0; i &lt; TEST_RUNS; i++)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum33>  33:</SPAN>                 {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum34>  34:</SPAN>                     sw.Start();</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum35>  35:</SPAN>                     var qryAnyCust = compiledCustQuery(ctx, <SPAN style="COLOR: black">"C"</SPAN>);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum36>  36:</SPAN>  </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum37>  37:</SPAN>                     <SPAN style="COLOR: black">if</SPAN> (qryAnyCust.Any())</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum38>  38:</SPAN>                     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum39>  39:</SPAN>                         var qryCust = compiledCustQuery(ctx, <SPAN style="COLOR: black">"C"</SPAN>);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum40>  40:</SPAN>                         Console.Out.Write(<SPAN style="COLOR: black">"{0} Cust records, "</SPAN>,qryCust.ToList().Count());</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum41>  41:</SPAN>                     }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum42>  42:</SPAN>                     sw.Stop();</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum43>  43:</SPAN>                     totalTime += sw.Elapsed.TotalMilliseconds;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum44>  44:</SPAN>                     iterations++;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum45>  45:</SPAN>                     Console.Out.WriteLine(<SPAN style="COLOR: black">"iteration = {0} Last:{1}ms, Average:{2}ms"</SPAN>, i, sw.Elapsed.TotalMilliseconds, (totalTime / (<SPAN style="COLOR: black">double</SPAN>)iterations));</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum46>  46:</SPAN>                     <SPAN style="COLOR: black">if</SPAN> (i == 0) <SPAN style="COLOR: #008000">//Mark profile data after first pass as it is warmup</SPAN></PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum47>  47:</SPAN>                     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum48>  48:</SPAN>                         <SPAN style="COLOR: #008000">//Mark profiling data</SPAN></PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum49>  49:</SPAN>                         DataCollection.CommentMarkProfile(100, <SPAN style="COLOR: black">"After Warmup - Any ON compiled query"</SPAN>);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum50>  50:</SPAN>                     }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum51>  51:</SPAN>                     sw.Reset();</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum52>  52:</SPAN>                 }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum53>  53:</SPAN>                 Console.Out.WriteLine(<SPAN style="COLOR: black">""</SPAN>);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum54>  54:</SPAN>             }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum55>  55:</SPAN>             DataCollection.CommentMarkProfile(110, <SPAN style="COLOR: black">"Queries Done"</SPAN>);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum56>  56:</SPAN>             Console.WriteLine(<SPAN style="COLOR: black">"Press and key to continue...."</SPAN>);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum57>  57:</SPAN>             Console.Read();</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum58>  58:</SPAN>         }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum59>  59:</SPAN>     }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum60>  60:</SPAN> }</PRE><!--CRLF--></DIV></DIV>
<P>Now it’s time to profile the application. In the Performance Explorer, click on the icon for “Launch with Profiling”.</P>
<P><B>Note</B>: If you see an error message about not being able to open the profiler driver, select “Yes” to upgrade the credential of the current user.</P>
<P>The application will execute and then press the &lt;Enter&gt; key to close the application. Visual Studio will churn for a few minutes and then show the Profile report, but were not ready to study it just yet. These results still contain the warm-up code profile data which includes the loading of the metadata and connecting to the SQL server. To look only at the LINQ query execution, change the “Current View” of the report to “Marks” via the drop down list. A list of profile data marks will be shown including the ones that were set in the code. Highlight all of the marks between the two custom code marks (100 and 110), right-click and select “Add Filter on Marks”:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfFilter_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfFilter_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfFilter_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=ProfFilter border=0 alt=ProfFilter src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfFilter_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfFilter_thumb.png" width=508 height=361 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfFilter_thumb.png"></A> </P>
<P>Now press the “Execute Filter” button which is the second one to the right of the Current View dropdown list. This will filter the profile data and only include data between the marks we inserted via code and then it will change the current view back to the Summary view. Scrolling down on the refreshed report shows the code HotPath(the section of the code that took the majority of the time executing):</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReport_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReport_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReport_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=ProfReport border=0 alt=ProfReport src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReport_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReport_thumb.png" width=516 height=370 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReport_thumb.png"></A> </P>
<P>As shown above, the call to <I>System.Linq.Queryable.Any</I>() is shown as the most expensive call. This call should be fast because it should simply check if any records are return in the result set so we need to drill in further to find the root cause.</P>
<P>To do this an additional option needs to be changed. Select “Debug | Options and Settings…” from the Visual Studio main menu. Click on “Performance Tools” and uncheck the “Enable Just My Code for profiler reports (sampling)” in the “Just My Code” section and press the “Ok” button. Now re-run the profiler to generate a second report and then filter that report on our code marks as we did above.</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReportdotNet_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReportdotNet_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReportdotNet_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=ProfReportdotNet border=0 alt=ProfReportdotNet src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReportdotNet_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReportdotNet_thumb.png" width=524 height=383 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ProfilingEntityFrameworkusingtheVisualSt_C805/ProfReportdotNet_thumb.png"></A> </P>
<P>Now the report shows a lot more detail. The <I>System.Data.Query.PlanCompiler</I> class is being called even though the query should have already been compiled the first time we accessed it during our warm-up pass. As discussed in the previous blog entry, the call to the <EM>Any()</EM> method on the IQueriable is causing the query to re-compile each time which is an expensive operation.</P>
<P><B>CONCLUSION</B></P>
<P>As you can see, the Visual Studio 2010 Profiler can be a powerful tool to track down potential bottlenecks in your Entity Framework code or other parts of your application. And using the Profiler APIs, provides an easy way to hone in on performance characteristics of specific parts of an application. So go forth and profile that code, you never know what you will uncover. </P>
<P>Author: Dana Kaufman</P>
<P>Reviewers: Daniel Simmons, Jaime Alva Bravo, Paolo Salvatori</P>]]></content:encoded>
    </item>
    <item>
      <title>Isolating Performance with Precompiled/Pre-generated Views in the Entity Framework 4</title>
      <link>https://docs.microsoft.com/archive/blogs/dmcat/isolating-performance-with-precompiledpre-generated-views-in-the-entity-framework-4</link>
      <pubDate>Wed, 21 Apr 2010 14:23:08 GMT</pubDate>
      <dc:creator><![CDATA[Jaime Alva]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmcat/2010/04/21/isolating-performance-with-precompiledpre-generated-views-in-the-entity-framework-4/</guid>
      <description><![CDATA[Introduction  Working with customer’s solutions, we often have to track down potential performance...]]></description>
      <content:encoded><![CDATA[<p><b>Introduction</b></p>  <p>Working with customer’s solutions, we often have to track down potential performance issues or uncover areas for improvement. One of the techniques is to try and measure the relative performance gained using the different configurations or features (likely in a staging/testing environment). When working with Entity Framework 4 one of the potential optimizations is to use precompiled views where Entity Framework query views are pre-built and compiled into the application; which otherwise, the entity framework would have to generate on the fly (extra resources being required). The following are some useful references on precompiled views:</p>  <p>· MSDN - <a href="https://msdn.microsoft.com/en-us/library/bb896240.aspx">How to: Pre-Generate Views to Improve Query Performance (Entity Framework)</a></p>  <p>· EF Team Blog - <a href="https://blogs.msdn.com/adonet/archive/2008/06/20/how-to-use-a-t4-template-for-view-generation.aspx">How to use a T4 template for View Generation</a></p>  <p>This sample application shows one possible way to test potential performance gains and resource utilization when using pre-generated views by providing a performance comparison between runs with precompiled views and without. You can download the sample code <a href="https://cid-0ed76ff674b5e404.skydrive.live.com/self.aspx/.Public/PerfSample.zip">here</a>.</p>  <p>When isolating performance, a good idea is to focus on a very narrow piece, preferable a section that gets the most use. <a href="https://msdn.microsoft.com/en-us/magazine/cc337887.aspx">Using Visual Studio Profiler to find the bottleneck</a> can point to the slowest query. Then by leveraging the analysis techniques discussed below,<b> </b>the performance gains can be observed/studied.</p>  <p>Note: that the <a href="https://cid-0ed76ff674b5e404.skydrive.live.com/self.aspx/.Public/PerfBlog.zip">sample</a> for this article leverages the T4 template for View Generation mentioned in <a href="https://blogs.msdn.com/adonet/archive/2008/06/20/how-to-use-a-t4-template-for-view-generation.aspx">the EF Team Blog link</a> above.</p>  <p><b>Analyzing the Sample</b></p>  <p><i>The database</i> - The complete <a href="https://cid-0ed76ff674b5e404.skydrive.live.com/self.aspx/.Public/PerfSample.zip">sample code</a> (solution named: PerfSample), executes a query against a local database named PerfSample. To create it, the 2 SQL scripts found at the root of the downloadable ZIP file need to be executed against an empty Database. Open the first one, named EFModelGen.SQL, with Microsoft SQL Server Management Studio and Execute it. This will not create the entities yet but instead, it will generate the required SQL script. Copy and paste the results into a new query and run it against your empty database, this will create 200 empty entities. To create records for the entities Type1 and Type2 run the second script, named PopulateData.sql. It contains 2 variables: Type1RecordCount and oneToMany. The first indicates the number of records to be created in entity Type1, and since entities Type1 and Type2 have one-to-many relationship, the second variable indicates how many Type2 records will be created per each Type1 record. </p>  <p>The sample executes a LINQ select statement with a join against the Type1 and Type2 entities. For the purpose of testing precompiled views, the results need to be materialized (turning data records into “real” objects) hence, the sample runs <i>ToList().Count()</i> against the query results, the simple code is as follows.</p>  <pre class="csharpcode">   <font color="#0000ff">var</font> type1WithType2 = <font color="#0000ff">from</font> t1 <span class="kwrd">in</span> context.Type1
                        <font color="#0000ff">join</font> t2 <span class="kwrd">in</span> context.Type2
                        <font color="#0000ff">on</font> t1.Type1Id <font color="#0000ff">equals</font> t2.Type1_Type1Id
                           <font color="#0000ff">select</font> <span class="kwrd">new</span>
                           { t1.Type1_Col30, t2.Type2_Col30 };
   type1WithType2.ToList().Count();</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style><style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p><font size="2" face="Consolas"></font></p>

<p></p>

<p>Once the query is identified, execution time (performance) and memory usage (resource) is recorded. To measure time, the <a href="https://msdn.microsoft.com/en-us/library/ebf7z0sw(v=VS.90).aspx"><i>StopWatch</i></a> class is used. For recording memory usage, a memory reading is collected into long integers before and after the query is executed and then the numbers are subtracted, which will provide only the memory used by the query. To look at <a href="https://msdn.microsoft.com/en-us/library/f144e03t(VS.80).aspx">Managed memory</a> (memory used only by the framework), first the <a href="https://msdn.microsoft.com/en-us/library/0xy59wtx.aspx">garbage collector (GC)</a> is forced to run, that way obtaining a clearer read of the memory being used by the framework. Note that this is purposely done before the stopwatch starts since the <a href="https://msdn.microsoft.com/en-US/library/system.gc.gettotalmemory(v=VS.80).aspx"><i>GetTotalMemory (true</i></a><i>) </i>method may take a little while to return while the GC is run (which can be unpredictably long or short).</p>

<pre class="csharpcode">   startManageMemoryBytes = GC.GetTotalMemory(<span class="kwrd">true</span>); <span class="rem">//Force GC</span>
   stopWatch.Start();

      <span class="rem">//[Query/code to analyze]</span>

   stopWatch.Stop();
   endManageMemoryBytes = GC.GetTotalMemory(<span class="kwrd">false</span>);</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p></p>

<p>The program is compiled with the <a href="https://www.microsoft.com/visualstudio/en-us/">Visual Studio </a>and to streamline things a bit more, it is built in <a href="https://msdn.microsoft.com/en-us/library/wx0123s5.aspx">Release mode</a>, the SQL server is local to the machine (minimizing network delays) and its affinity set to CPU1 (minimizing CPU <a href="https://en.wikipedia.org/wiki/Context_switch">context switching</a> between SQL and the application), tests were executed on a dual-proc machine. </p>

<p>The query above is executed 3 times (call to <i>QueryToTest(context)</i>), in order to collect more even results. </p>

<p><b>Performing the tests</b></p>

<p>The sample has to first be prepared to either run in precompiled mode or in standard mode. To setup a precompiled run, make sure the PerfSample.view.tt is included in the solution and that it has a corresponding PerfSample.views.cs file (if the .cs file is missing then it can be generated by doing a right-click on the T4 template PerfSample.view.tt and choosing ‘Run Custom Tool’) and then clean and rebuilding the solution. Likewise, to setup a run without precompiled views, exclude the T4 template PerfSample.view.tt from the project (right-click and choose to ‘Exclude From Project’) then clean and rebuild the solution.</p>

<p>The sample program is a simple console application that is executed via a small DOS batch file. The batch file runs the program 3 times and sends the info to the console; it is named <i>runtest.bat</i> and is found under <i>…/bin/release</i> directory. To make it easier to analyze, the results are piped to a text file in the same directory.</p>

<p>The following DOS commands are executed to collect the respective results, after the proper changes are made (as explained above)</p>

<pre class="csharpcode">   Runtests &gt; WithPreCompiledViews.txt
   Runtests &gt; WithoutPreCompiledViews.txt</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>NOTE: To append results into an existing file, replace the single less-than symbol (“&gt;”) with the double <i>pipe</i> command “&gt;&gt;” </p>

<p>The test batch file is run multiple times to get a good sample of performance times.</p>

<p><b>The Results</b> </p>

<p>
  <table border="1" cellspacing="0" cellpadding="0" width="532"><tbody>
      <tr>
        <td valign="top" width="264">
          <p align="center"><b>without </b>precompiled views<b></b></p>
        </td>

        <td valign="top" width="266">
          <p align="center"><b>with </b>precompiled views<b></b></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="264">
          <p><font size="2" face="Consolas">..\bin\Release&gt;call PerfSample </font></p>

          <p><font size="2" face="Consolas">|Time MilSec |Manage Bytes | 
              <br />|--------------------------| 

              <br />|&#160;&#160;&#160;&#160; 8,009&#160; | 69,174,356&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 810&#160; | 53,299,352&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 815&#160; | 53,299,388&#160; | </font></p>

          <p><font size="2" face="Consolas">..\bin\Release&gt;call PerfSample </font></p>

          <p><font size="2" face="Consolas">|Time MilSec |Manage Bytes | 
              <br />|--------------------------| 

              <br />|&#160;&#160;&#160;&#160; 7,629&#160; | 69,169,948&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 847&#160; | 53,303,016&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 858&#160; | 53,305,532&#160; | </font></p>

          <p><font size="2" face="Consolas">..\bin\Release&gt;call PerfSample </font></p>

          <p><font size="2" face="Consolas">|Time MilSec |Manage Bytes | 
              <br />|--------------------------| 

              <br />|&#160;&#160;&#160;&#160; 8,057&#160; | 68,123,116&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 800&#160; | 53,303,064&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 794&#160; | 53,304,332&#160; </font><font size="2" face="Consolas">|</font></p>
        </td>

        <td valign="top" width="266">
          <p><font size="2" face="Consolas">..\bin\Release&gt;call PerfSample </font></p>

          <p><font size="2" face="Consolas">|Time MilSec |Manage Bytes | 
              <br />|--------------------------| 

              <br />|&#160;&#160;&#160;&#160; 3,287&#160; | 73,282,032&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 813&#160; | 53,306,136&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 897&#160; | 53,301,052&#160; | </font></p>

          <p><font size="2" face="Consolas">..\bin\Release&gt;call PerfSample </font></p>

          <p><font size="2" face="Consolas">|Time MilSec |Manage Bytes | 
              <br />|--------------------------| 

              <br />|&#160;&#160;&#160;&#160; 3,269&#160; | 73,283,292&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 805&#160; | 53,299,816&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 837&#160; | 53,305,532&#160; | </font></p>

          <p><font size="2" face="Consolas">..\bin\Release&gt;call PerfSample </font></p>

          <p><font size="2" face="Consolas">|Time MilSec |Manage Bytes | 
              <br />|--------------------------| 

              <br />|&#160;&#160;&#160;&#160; 3,257&#160; | 73,283,548&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 815&#160; | 53,306,776&#160; | 

              <br />|&#160;&#160;&#160;&#160;&#160;&#160; 806&#160; | 53,299,004&#160; |</font><font size="2" face="Consolas">&#160; <br /></font></p>
        </td>
      </tr>
    </tbody></table>
</p>

<p>This is well in line with the expected behavior of <a href="https://msdn.microsoft.com/en-us/library/bb896240.aspx">precompiled views</a>. The test runs made without precompiled views have to first generate the set of views to access the database so, it is expected that their elapsed time will be greater. From the results above, the time lapse for precompiled views is over twice as fast but not for subsequent runs since the view is already generated and therefore reused. </p>

<p>In the same manner, precompiled views should give us a lower memory footprint. For managed memory, the first run uses about 5~7% less memory and subsequent are in both cases similar. Also, in both cases, the drop in memory usage is likely explained by the fact that unused memory is being reclaimed by the system.</p>

<p>As a way to further explore the behavior of pre-generated views, the <a href="https://cid-0ed76ff674b5e404.skydrive.live.com/self.aspx/.Public/PerfSample.zip">sample</a> has one line of code commented-out, this is the method <i>PreRun(context)</i> which does a select count of all the members in both the Products and the TransactionHistory entities, the same entities used in the query. And it does this by reusing the ObjectContext instance (no statistics are recorded). Running the test with this method uncommented, will result in very similar time lapses and memory usage for both the precompiled and not-precompiled executions. This is because the Query from the <i>QueryToTest(context)</i> method is reusing the already generated views from <i>PreRun(context)</i> since they share the same ObjectContext.</p>

<p><b>Conclusion</b></p>

<p>This empirically demonstrates the performance improvement offered by precompiled views, by pre-constructing the Entity Framework views, the first run of the query was about 2.4 times quicker and there also was an improvement in memory usage. Since the first execution of the query is where the performance gain is, leveraging pre-generated views in at least two cases will be of significant value: the warm up of a system and the execution of infrequently run queries. The use of less memory is also advantageous and is due to no longer having the overhead of keeping and creating the views. </p>

<p>Results are likely going to vary depending on your solution, particularly the model size and the amount of records being queried, so the sample should be tailored to match, as much as possible, your particular solution, however gains should be noticeable. </p>]]></content:encoded>
    </item>
    <item>
      <title>Potential Performance Issues with Compiled LINQ Query Re-Compiles</title>
      <link>https://docs.microsoft.com/archive/blogs/dmcat/potential-performance-issues-with-compiled-linq-query-re-compiles</link>
      <pubDate>Mon, 08 Mar 2010 13:24:00 GMT</pubDate>
      <dc:creator><![CDATA[dkaufman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmcat/2010/03/08/potential-performance-issues-with-compiled-linq-query-re-compiles/</guid>
      <description><![CDATA[When calling a query multiple times with Entity Framework the recommended approach is to use...]]></description>
      <content:encoded><![CDATA[<P>When calling a query multiple times with Entity Framework the recommended approach is to use compiled LINQ queries. Compiling a query results in a performance hit the first time you use the query but subsequent calls execute much faster. The <A href="https://msdn.microsoft.com/en-us/library/system.data.objects.compiledquery.aspx" mce_href="https://msdn.microsoft.com/en-us/library/system.data.objects.compiledquery.aspx">CompiledQuery</A> class has functionality to compile and assist in caching the resulting database command from a query.</P>
<P>An example of a compiled query is show below. The query returns a list of Customers from the <A href="https://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en" mce_href="https://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en">Northwinds sample database</A> whose CustomerID starts with a specific string that is passed in as a parameter:</P><PRE class=code><SPAN style="COLOR: blue">static </SPAN><SPAN style="COLOR: #2b91af">Func</SPAN>&lt;<SPAN style="COLOR: #2b91af">NorthwindEntities</SPAN>, <SPAN style="COLOR: blue">string</SPAN>, <SPAN style="COLOR: #2b91af">IQueryable</SPAN>&lt;<SPAN style="COLOR: #2b91af">Customer</SPAN>&gt;&gt; compiledCustQuery =
   <SPAN style="COLOR: #2b91af">CompiledQuery</SPAN>.Compile((<SPAN style="COLOR: #2b91af">NorthwindEntities </SPAN>ctx, <SPAN style="COLOR: blue">string </SPAN>start) =&gt;
   (<SPAN style="COLOR: blue">from </SPAN>c <SPAN style="COLOR: blue">in </SPAN>ctx.Customers
    <SPAN style="COLOR: blue">where </SPAN>c.CustomerID.StartsWith(start)
    <SPAN style="COLOR: blue">select </SPAN>c));</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>
<P>A few weeks ago while working with a partner on EF performance optimization, we ran into an interesting case where the EF code segment was executing much slower than expected. The Visual Studio Profiler showed that the code was spending an inordinate amount of time when executing a compiled query. Digging into the code showed that one particular operation on the compiled query was causing it to recompile every time it was executed. The code was checking to see if the result set returned any records. There are multiple ways to accomplish this. A common way is to use <I>.Count()!=0</I> or <I>Any()</I>. In this case the compiled query returned an <EM>IQueryable</EM>. Calling <I>Count()</I> or <I>Any() </I>was causing the query to re-compile.</P>
<P>I wrote a small application to duplicate this issue using the Northwinds database. The code executes the compiled query to see if any records are returned. If there are records in the result set, it executes the query again and returns all the rows (the <I>ToList().Count()</I> makes sure all results from the second query are materialized in memory). Below is a snippet of code showing the two queries:</P><PRE class=code><SPAN style="COLOR: blue">var </SPAN>qryAnyCust = compiledCustQuery(ctx, <SPAN style="COLOR: #a31515">"C"</SPAN>);

<SPAN style="COLOR: blue">if </SPAN>(qryAnyCust.Any())
{
    <SPAN style="COLOR: blue">var </SPAN>qryCust = compiledCustQuery(ctx, <SPAN style="COLOR: #a31515">"C"</SPAN>);
    qryCust.ToList().Count();
}</PRE>
<P>Running the Visual Studio profiler shows the following Hot Path:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image001_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image001_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image001_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=clip_image001 border=0 alt=clip_image001 src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image001_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image001_thumb.png" width=535 height=208 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image001_thumb.png"></A></P>
<P>Over 83.33% of the time is spent executing the <EM>System.Linq.Queryable.Any()</EM> class and only 16.67% of the time was spent actually executing the query. Executing the sample application yielded an execution time of approximately <B>9ms</B>.</P>
<P>Next the code was modified to use a second version of the compiled query that contained the .Any() method in the query and returned a Boolean instead of an <EM>IQueryable</EM>. Below is the second query:</P><PRE class=code><SPAN style="COLOR: blue">static </SPAN><SPAN style="COLOR: #2b91af">Func</SPAN>&lt;<SPAN style="COLOR: #2b91af">NorthwindEntities</SPAN>, <SPAN style="COLOR: blue">string</SPAN>, <SPAN style="COLOR: blue">bool</SPAN>&gt; compiledAnyCustQuery =
   <SPAN style="COLOR: #2b91af">CompiledQuery</SPAN>.Compile((<SPAN style="COLOR: #2b91af">NorthwindEntities </SPAN>ctx, <SPAN style="COLOR: blue">string </SPAN>start) =&gt;
   (<SPAN style="COLOR: blue">from </SPAN>c <SPAN style="COLOR: blue">in </SPAN>ctx.Customers
    <SPAN style="COLOR: blue">where </SPAN>c.CustomerID.StartsWith(start)
    <SPAN style="COLOR: blue">select </SPAN>c).Any());</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>
<P>The query execution code was changed to call the above query to check if any records would be returned and then the query from the previous example to retrieve the actual records. This code is shown below:</P><PRE class=code><SPAN style="COLOR: blue">if </SPAN>(compiledAnyCustQuery(ctx, <SPAN style="COLOR: #a31515">"C"</SPAN>))
{
    <SPAN style="COLOR: blue">var </SPAN>qryCust = compiledCustQuery(ctx, <SPAN style="COLOR: #a31515">"C"</SPAN>);
    qryCust.ToList().Count();
}</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>
<P>Looking at the profiler output of the above code shows that the call to <I>Any()</I> is no longer the bottleneck and that actually invoking the query now takes the majority of the time as expected:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image003_2.jpg" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image003_2.jpg" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image003_2.jpg"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=clip_image003 border=0 alt=clip_image003 src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image003_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image003_thumb.jpg" width=529 height=229 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image003_thumb.jpg"></A></P>
<P>Executing this code displayed much better performance. The test executed in only <B>6ms</B> almost a 33% performance increase from a small change to a single query.</P>
<P>An alternative way to prevent re-compilation of the compiled query is to return an <EM>IEnumerable</EM> instead of <EM>IQueryable</EM> for the cached query. Using <EM>IEnumerable</EM> causes the query data to be returned from the server and then allows for evaluation and further refinement of the results set locally. For instance, executing a <I>Count() </I>on an <EM>IEnumerable</EM> from a query returns the number or records contained in the in-memory result set.</P>
<P><B>Note:</B> Using <EM>IEnumerable</EM> will cause all of the query results data to be transferred from the server to the client. This can be a drain on memory and performance on the client if the query returns a <U>l</U>arge number of records. This might not be the best approach if you have <B>large result sets</B> and simply need to get record counts. </P>
<P>Below is the code from the sample application which returns the compiled query as an <EM>IEnumerable</EM> instead of <EM>IQueryable</EM>:</P><PRE class=code><SPAN style="COLOR: blue">static </SPAN><SPAN style="COLOR: #2b91af">Func</SPAN>&lt;<SPAN style="COLOR: #2b91af">NorthwindEntities</SPAN>, <SPAN style="COLOR: blue">string</SPAN>, <SPAN style="COLOR: #2b91af">IEnumerable</SPAN>&lt;<SPAN style="COLOR: #2b91af">Customer</SPAN>&gt;&gt; compiledEnumCustQuery =
   <SPAN style="COLOR: #2b91af">CompiledQuery</SPAN>.Compile((<SPAN style="COLOR: #2b91af">NorthwindEntities </SPAN>ctx, <SPAN style="COLOR: blue">string </SPAN>start) =&gt;
   (<SPAN style="COLOR: blue">from </SPAN>c <SPAN style="COLOR: blue">in </SPAN>ctx.Customers
    <SPAN style="COLOR: blue">where </SPAN>c.CustomerID.StartsWith(start)
    <SPAN style="COLOR: blue">select </SPAN>c));</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>
<P>A third version of the query execution, is show below, that checks to see if any records would be returned and then the query from the previous example to retrieve the actual records:</P><PRE class=code><SPAN style="COLOR: blue">if </SPAN>(qryEnumAnyCust.Any())
{
    <SPAN style="COLOR: blue">var </SPAN>qryCust = compiledCustQuery(ctx, <SPAN style="COLOR: #a31515">"C"</SPAN>);
    qryCust.ToList().Count();
}</PRE><A href="https://11011.net/software/vspaste" mce_href="https://11011.net/software/vspaste"></A>
<P>Executing the above code displayed similar performance to the previous test that used the compiled queries containing the <EM>Any()</EM>. The test executed in only <B>6.7ms</B> which was much better than the original code. Profiling the <EM>IEnumerable</EM> test shows that now most of the execution time is spent in the <EM>Any()</EM> method on the <EM>IEnumerable</EM> which should execute quickly because the values are in memory:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image004_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image004_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image004_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=clip_image004 border=0 alt=clip_image004 src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image004_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image004_thumb.png" width=538 height=291 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/PotentialPerformanceIssueswithCompiledLI_BC5E/clip_image004_thumb.png"></A></P>
<P>In the case of our partner, changing their code to use compiled queries to contain the <I>Any()</I> and return a <I>Boolean</I> boosted their performance 450% because their code checked if queries returned results in multiple places.</P>
<P>Query recompile is not limited to <EM>Any()</EM> or <EM>Count()</EM> operations. It can happen with <U>any LINQ operator that is applied on top of a compiled query</U>. So be on the lookout for query re-compilation in your code. It can unknowingly impact performance. In a future post I will cover in more detail the use the Visual Studio Profiler to uncover bottlenecks in the Entity Framework.</P>
<P>Author: Dana Kaufman <BR>Reviewers: Daniel Simmons, Diego Vega, Jaime Alva Bravo,&nbsp; Peter Scharlock</P>]]></content:encoded>
    </item>
    <item>
      <title>Model Driven Content Based Routing using SQL Server Modeling CTP – Part II</title>
      <link>https://docs.microsoft.com/archive/blogs/dmcat/model-driven-content-based-routing-using-sql-server-modeling-ctp-part-ii</link>
      <pubDate>Mon, 14 Dec 2009 15:14:00 GMT</pubDate>
      <dc:creator><![CDATA[dkaufman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmcat/2009/12/14/model-driven-content-based-routing-using-sql-server-modeling-ctp-part-ii/</guid>
      <description><![CDATA[Author: Dana Kaufman 
Reviewers: Jaime Alva Bravo, Chris Sells, Kraig Brockschmidt, Matthew Snider,...]]></description>
      <content:encoded><![CDATA[<P>Author: Dana Kaufman </P>
<P>Reviewers: Jaime Alva Bravo, Chris Sells, Kraig Brockschmidt, Matthew Snider, David Miller</P>
<H3>Introduction</H3>
<P>The <A href="https://code.msdn.microsoft.com/RouterManager" mce_href="https://code.msdn.microsoft.com/RouterManager">RouterManager sample</A> uses the recently released SQL Server Modeling CTP and the new WCF Routing Service in .NET 4 to show how to do model driven content based message routing. <A href="https://blogs.msdn.com/dmcat/archive/2009/11/16/model-driven-content-based-routing-using-sql-server-modeling-ctp-part-i.aspx" mce_href="https://blogs.msdn.com/dmcat/archive/2009/11/16/model-driven-content-based-routing-using-sql-server-modeling-ctp-part-i.aspx">Part I</A> of the series <A href="https://blogs.msdn.com/dmcat/archive/2009/11/16/model-driven-content-based-routing-using-sql-server-modeling-ctp-part-i.aspx" mce_href="https://blogs.msdn.com/dmcat/archive/2009/11/16/model-driven-content-based-routing-using-sql-server-modeling-ctp-part-i.aspx">Model Driven Content Based Routing using SQL Server Modeling CTP</A> covered the overall architecture of the sample application. Part II will drill into the domain-specific language (DSL) developed using the M language features which makes it easy to configure Routing Service routing rules.</P>
<P>The routing language in the RouterManager sample consists of easy to understand, human readable text. The example listing below shows a router configuration implemented in a router DSL:</P>
<DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet>router begin<BR>  if header version = "Precise" priority 0 destination https://localhost:9090/servicemodelsamples/regularcalc<BR>  if header version = "Rounded" destination https://localhost:9091/servicemodelsamples/roundingcalc<BR>  if endpoint = "ServiceA" destination https://localhost:9090/servicemodelsamples/regularcalc, https://localhost:9091/servicemodelsamples/roundingcalc<BR>end</PRE><BR></DIV>
<P align=center><B>Listing 1</B></P>
<P>As seen in the listing above, a router configuration starts with the text <FONT size=2 face="Courier New"><EM>router begin</EM></FONT> and end with <FONT size=2 face="Courier New"><EM>end</EM></FONT>. Router configurations consist of a set of filters which are rules that tell the Routing Service what content to look for in the incoming message and where matching messages should be sent. The router language uses <FONT size=2 face="Courier New"><EM>if</EM></FONT> statements to specify a filter. After the <FONT size=2 face="Courier New"><EM>if</EM></FONT>&nbsp; keyword come the filter type. The RouterManager host supports the following filter types: </P>
<P>
<TABLE border=1 cellSpacing=0 cellPadding=0>
<TBODY>
<TR>
<TD vAlign=top width=146>
<P><B><U>Filter</U></B></P></TD>
<TD vAlign=top width=812>
<P><B><U>Description</U></B></P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>header</P></TD>
<TD vAlign=top width=812>
<P>Message contains a SOAP header with a specific value(supports SOAP 1.1 and 1.2 envelopes)</P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>endpoint</P></TD>
<TD vAlign=top width=812>
<P>Message arrives on a specific endpoint</P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>address</P></TD>
<TD vAlign=top width=812>
<P>Message arrives on a specific address</P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>addressprefix</P></TD>
<TD vAlign=top width=812>
<P>Message arrives on an address that contains the specified prefix</P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>matchall</P></TD>
<TD vAlign=top width=812>
<P>Any message</P></TD></TR></TBODY></TABLE></P>
<P>The <FONT size=2 face="Courier New"><EM>if</EM></FONT> statement has specific syntax for each filter. For instance the <FONT size=2 face="Courier New"><EM>header</EM></FONT> filter shown above requires a field to be specified so that the Routing Service knows what SOAP header to look for in the incoming message. A value is also required on most of the filters (<EM> <FONT size=2 face="Courier N">= “{value}” </FONT>&nbsp;</EM>) to tell the Routing Service which pieces of data needs to be match for the filter rule to be true. Also, each rule filter can have an optional priority value which determines the execution order of the filters. Lastly, each filter can have one or more destinations to which the message can be routed.</P>
<H3>Domain-Specific Language for Router Configuration</H3>
<P>The “M” language features of the SQL Server Modeling CTP can be used to project arbitrary textual data into a data model. In the RouterManager sample, the language features are used to parse the configuration text and turn it into data which can be stored in the Repository database. The RouterManager sample contains a file called RouterGrammar.mg which defines a language called RouterConfigure that tells the “M” language compiler how to parse the above configuration text. The RouterGrammar file along with the model for the Router configuration can be found in the RouterModel project in the RouterManager Visual Studio solution. The CTP contains a handy tool for developing languages called “Intellipad”, a screenshot of the RouterGrammar.mg file in “Intellipad” is shown below:</P>
<P align=center><B>&nbsp;<A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_4.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_4.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_4.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_thumb_1.png" width=526 height=403 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_thumb_1.png"></A> <BR>Image 1</B></P>
<P>In the above picture, “Intellipad” is in a special language development mode. To get it into this mode, create or load a .mg language file then select “<STRONG>DSL</STRONG>” in the “Intillipad” menu and then choose “<STRONG>Open File As Input and Show Output…</STRONG>” which will bring up a file open dialog. Select a text file with an .mg extension as input for the language and “Intellipad” will open the windows shown above. The input text is shown in the right window, the center window contains the language definition and the right window shows the parsed output. The window on the bottom shows any errors.</P>
<P>The RouterConfigure language is contained in a module called RouterGrammar. A grammar is a set of rules which determine if sequences of characters conform to a language. The grammar parser will parse the input text based on the rules of the grammar and build a syntax tree which is the resulting hierarchy of data that was parsed. This syntax tree can be used in a number of ways in an application including storing the parsed data (e.g. in the SQL Server Modeling Services Repository or as XML) or iterating through the tree in memory at runtime directly in your application. The RouterManager sample uses the “M” tool chain to generate the syntax tree as a set of model values that get imported into the SQL Server Modeling Services Repository.</P>
<P>Below is the full listing of the RouterConfigure language grammar:</P>
<DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; HEIGHT: 258px; MAX-HEIGHT: 300px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper>
<DIV style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum1>   1:</SPAN> module RouterGrammar{</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum2>   2:</SPAN>   language RouterConfigure{</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum3>   3:</SPAN>   syntax Main = TkStart s:Statement* TkEnd =&gt; RouterRules{ valuesof(s)};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum4>   4:</SPAN>   </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum5>   5:</SPAN>   syntax Statement = TkIf a:FilterType  =&gt; {Filter =&gt; a};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum6>   6:</SPAN>  </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum7>   7:</SPAN>   syntax FilterType = h:Header  =&gt; h | </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum8>   8:</SPAN>                       ap:AddressPrefix =&gt; ap | </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum9>   9:</SPAN>                       ad:Address=&gt;ad | </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum10>  10:</SPAN>                       ac:Action =&gt; ac | </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum11>  11:</SPAN>                       ma:MatchAll =&gt; ma |</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum12>  12:</SPAN>                       ep:Endpoint =&gt; ep | </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum13>  13:</SPAN>                       aa:And =&gt;aa | </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum14>  14:</SPAN>                       c:Custom =&gt; c;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum15>  15:</SPAN>                       </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum16>  16:</SPAN>   syntax Header = a:TkHeader f:TkField o:TkOperator v:TkValue p:Priority TkTarget t:Destinations(TkDestination,<SPAN style="COLOR: black">","</SPAN>) </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum17>  17:</SPAN>    =&gt; {action =&gt; a, field=&gt;f,<SPAN style="COLOR: black">operator</SPAN>=&gt;o, fieldvalue=&gt;v, priority=&gt;p, Destinations =&gt; t};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum18>  18:</SPAN>   syntax Action = a:TkAction o:TkOperator v:TkValue p:Priority TkTarget t:Destinations(TkDestination,<SPAN style="COLOR: black">","</SPAN>)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum19>  19:</SPAN>     =&gt; {action =&gt; a, <SPAN style="COLOR: black">operator</SPAN>=&gt;o, field=&gt;<SPAN style="COLOR: black">""</SPAN>,fieldvalue=&gt;v, priority=&gt;p, Destinations =&gt; t};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum20>  20:</SPAN>   syntax AddressPrefix = a:TkAddressPrefix o:TkEquals v:TkValue p:Priority TkTarget t:Destinations(TkDestination,<SPAN style="COLOR: black">","</SPAN>)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum21>  21:</SPAN>     =&gt; {action =&gt; a, <SPAN style="COLOR: black">operator</SPAN>=&gt;o, field=&gt;<SPAN style="COLOR: black">""</SPAN>, fieldvalue=&gt;v, priority=&gt;p, Destinations =&gt; t};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum22>  22:</SPAN>   syntax Address = a:TkAddress o:TkEquals v:TkValue p:Priority TkTarget t:Destinations(TkDestination,<SPAN style="COLOR: black">","</SPAN>)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum23>  23:</SPAN>     =&gt; {action =&gt; a, <SPAN style="COLOR: black">operator</SPAN>=&gt;o, field=&gt;<SPAN style="COLOR: black">""</SPAN>, fieldvalue=&gt;v, priority=&gt;p, Destinations =&gt; t};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum24>  24:</SPAN>   syntax Endpoint = a:TkEndpoint o:TkEquals v:TkValue p:Priority TkTarget t:Destinations(TkDestination,<SPAN style="COLOR: black">","</SPAN>)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum25>  25:</SPAN>     =&gt; {action =&gt; a, <SPAN style="COLOR: black">operator</SPAN>=&gt;o, field=&gt;<SPAN style="COLOR: black">""</SPAN>, fieldvalue=&gt;v, priority=&gt;p, Destinations =&gt; t};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum26>  26:</SPAN>   syntax And = a:TkAnd a1:TKAndText p:Priority TkTarget t:Destinations(TkDestination,<SPAN style="COLOR: black">","</SPAN>)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum27>  27:</SPAN>     =&gt; {action =&gt; a, <SPAN style="COLOR: black">operator</SPAN>=&gt; <SPAN style="COLOR: black">""</SPAN>,field=&gt;<SPAN style="COLOR: black">""</SPAN>,fieldvalue=&gt;a1, priority=&gt;p, Destinations =&gt; t};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum28>  28:</SPAN>   syntax MatchAll = a:TkMatchAll p:Priority TkTarget t:Destinations(TkDestination,<SPAN style="COLOR: black">","</SPAN>)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum29>  29:</SPAN>     =&gt; {action =&gt; a, <SPAN style="COLOR: black">operator</SPAN>=&gt;<SPAN style="COLOR: black">""</SPAN>, field=&gt;<SPAN style="COLOR: black">""</SPAN>,fieldvalue=&gt;<SPAN style="COLOR: black">""</SPAN>, priority=&gt;p, Destinations =&gt; t};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum30>  30:</SPAN>   syntax Custom = a:TkCustom f:TKCustomType v:TkValue p:Priority  TkTarget t:Destinations(TkDestination,<SPAN style="COLOR: black">","</SPAN>)</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum31>  31:</SPAN>     =&gt; {action =&gt; a, <SPAN style="COLOR: black">operator</SPAN>=&gt;<SPAN style="COLOR: black">""</SPAN>, field=&gt;f, fieldvalue=&gt;v, priority=&gt;p, Destinations =&gt; t};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum32>  32:</SPAN>   syntax Priority = TkPriority n:TkNumber =&gt; n  | empty =&gt; <SPAN style="COLOR: black">""</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum33>  33:</SPAN>   syntax Destinations(dest, separator)  = n:dest=&gt; {{URL =&gt; n}} | l:Destinations(dest, separator) separator n:dest =&gt; { valuesof(l), {URL =&gt; n} };</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum34>  34:</SPAN>&nbsp; </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum35>  35:</SPAN>   </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum36>  36:</SPAN>   token TkStart = <SPAN style="COLOR: black">"router begin"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum37>  37:</SPAN>   token TkEnd = <SPAN style="COLOR: black">"end"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum38>  38:</SPAN>   token TkName = TkText;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum39>  39:</SPAN>   token TkIf = <SPAN style="COLOR: black">"if"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum40>  40:</SPAN>   token TkHeader = <SPAN style="COLOR: black">"header"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum41>  41:</SPAN>   token TkAction = <SPAN style="COLOR: black">"action"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum42>  42:</SPAN>   token TkAddressPrefix = <SPAN style="COLOR: black">"addressprefix"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum43>  43:</SPAN>   token TkAddress = <SPAN style="COLOR: black">"address"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum44>  44:</SPAN>   token TkAnd = <SPAN style="COLOR: black">"and"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum45>  45:</SPAN>   token TkMatchAll = <SPAN style="COLOR: black">"matchall"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum46>  46:</SPAN>   token TkEndpoint = <SPAN style="COLOR: black">"endpoint"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum47>  47:</SPAN>   token TkCustom = <SPAN style="COLOR: black">"custom"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum48>  48:</SPAN>   token TkPriority =<SPAN style="COLOR: black">"priority"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum49>  49:</SPAN>&nbsp; </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum50>  50:</SPAN>   token TkField = TkText;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum51>  51:</SPAN>   token TkOperator = TkEquals | <SPAN style="COLOR: black">"contains"</SPAN> | <SPAN style="COLOR: black">"startswith"</SPAN> | <SPAN style="COLOR: black">"endswith"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum52>  52:</SPAN>   token TkEquals = <SPAN style="COLOR: black">"="</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum53>  53:</SPAN>   token TkValue = <SPAN style="COLOR: black">'"'</SPAN> (any - <SPAN style="COLOR: black">'"'</SPAN> )* <SPAN style="COLOR: black">'"'</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum54>  54:</SPAN>   token TkTarget = <SPAN style="COLOR: black">"destination"</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum55>  55:</SPAN>   token TKAndText = (<SPAN style="COLOR: black">"A"</SPAN>..<SPAN style="COLOR: black">"Z"</SPAN> | <SPAN style="COLOR: black">"a"</SPAN>..<SPAN style="COLOR: black">"z"</SPAN> | <SPAN style="COLOR: black">"0"</SPAN>..<SPAN style="COLOR: black">"9"</SPAN> | <SPAN style="COLOR: black">"_"</SPAN> | <SPAN style="COLOR: black">","</SPAN>)+;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum56>  56:</SPAN>   token TKCustomType = (<SPAN style="COLOR: black">"A"</SPAN>..<SPAN style="COLOR: black">"Z"</SPAN> | <SPAN style="COLOR: black">"a"</SPAN>..<SPAN style="COLOR: black">"z"</SPAN> | <SPAN style="COLOR: black">"0"</SPAN>..<SPAN style="COLOR: black">"9"</SPAN> | <SPAN style="COLOR: black">"_"</SPAN> | <SPAN style="COLOR: black">"."</SPAN>)+;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum57>  57:</SPAN>   </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum58>  58:</SPAN>   token TkDestination = TkUrl; </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum59>  59:</SPAN>   token TkUrl = (<SPAN style="COLOR: black">"A"</SPAN>..<SPAN style="COLOR: black">"Z"</SPAN> | <SPAN style="COLOR: black">"a"</SPAN>..<SPAN style="COLOR: black">"z"</SPAN> | <SPAN style="COLOR: black">"0"</SPAN>..<SPAN style="COLOR: black">"9"</SPAN> | <SPAN style="COLOR: black">"_"</SPAN> | <SPAN style="COLOR: black">"/"</SPAN> | <SPAN style="COLOR: black">":"</SPAN> | <SPAN style="COLOR: black">"."</SPAN>  )+;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum60>  60:</SPAN>&nbsp; </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum61>  61:</SPAN>   token TkText = (<SPAN style="COLOR: black">"A"</SPAN>..<SPAN style="COLOR: black">"Z"</SPAN> | <SPAN style="COLOR: black">"a"</SPAN>..<SPAN style="COLOR: black">"z"</SPAN> | <SPAN style="COLOR: black">"0"</SPAN>..<SPAN style="COLOR: black">"9"</SPAN> | <SPAN style="COLOR: black">"_"</SPAN>)+;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum62>  62:</SPAN>   token TkNumber =(<SPAN style="COLOR: black">"0"</SPAN>..<SPAN style="COLOR: black">"9"</SPAN>)+;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum63>  63:</SPAN>   </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum64>  64:</SPAN>   interleave Whitespace = <SPAN style="COLOR: black">' '</SPAN> | <SPAN style="COLOR: black">'\t'</SPAN> | <SPAN style="COLOR: black">'\n'</SPAN> | <SPAN style="COLOR: black">'\r'</SPAN>;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum65>  65:</SPAN>   }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum66>  66:</SPAN> }</PRE><!--CRLF--></DIV></DIV><B>
<P align=center>Listing 2</P></B>
<P>In a language definition, the interleave indicates the rule for which values should be used as whitespace. For the RouterConfigure language, whitespace will be defined as spaces, tabs, carriage returns/linefeed, and commas. The interleave command (line 64) looks like this:</P>
<P><FONT size=2 face="Courier New">interleave Whitespace = ' ' | '\t' | '\n' | '\r' | ',';</FONT> </P>
<P>Tokens are used to designate rules that define the language. The language parser will try to match the tokens in the input text. Lines 36 to 62 define the tokens that make up the RouterConfigure language. For example, the token that signifies the beginning of a router configuration is called <FONT size=2 face="Courier New"><EM>TkStart</EM></FONT>, the <FONT size=2 face="Courier New"><EM>TkStart</EM></FONT> token tells the language parser to look specifically for the text “router begin”:</P>
<P><FONT size=2 face="Courier New">token TkStart = "router begin";</FONT> </P>
<P>Another token <FONT size=2 face="Courier New"><EM>TkNumber</EM></FONT> (line 62) is used for integer values. The definition for this token indicates that a number is made up of digits between “0” and “9” (the .. means between) and the “+” sign in the definition indicates a number can be made up of more than one of these characters:</P>
<P><FONT size=2 face="Courier New">token TkNumber = (“0”..”9”)+;</FONT></P>
<P>A token for text (line 61) is defined as one or more characters which can be any letter between A and Z (lower or upper case), any digit between 0 and 9, or an underscore. The definition for the text token looks like this:</P>
<P><FONT size=2 face="Courier New">token TkText = ("A".."Z" | "a".."z" | "0".."9" | "_")+;</FONT></P>
<P>And a field (<FONT size=2 face="Courier New"><EM>TkField</EM></FONT> line 50) and a name (<FONT size=2 face="Courier New"><EM>TkName</EM></FONT> line 38) tokens are made up of a <FONT size=2 face="Courier New"><EM>TkText</EM></FONT> token.</P>
<P>There are also tokens defined for each of the filter rules (lines 40 to 48). Other tokens define information needed for specific filters and other keywords such the token <FONT size=2 face="Courier New"><EM>TkTarget</EM></FONT> (line 54) which specifies the keyword that indicates a URL or set of URLs will follow.</P>
<P>Next the syntax defines how the tokens should be used (lines 3 to 33). The “M” language below is the syntax statement that tells how the tokens can be used to parse the input text. All “M” language files must have a <FONT size=2 face="Courier New"><EM>Main</EM></FONT> syntax statement which is the starting point for the grammar rules. The ConfigRouter main syntax looks like this (line 3):</P>
<P><FONT size=2 face="Courier New">syntax Main = TkStart s:Statement* TkEnd =&gt; RouterRules{ valuesof(s)};</FONT></P>
<P>The above indicates that first; there should be a <FONT size=2 face="Courier New"><EM>TkStart</EM></FONT> token in the text, then one or more <FONT size=2 face="Courier New"><EM>Statements</EM></FONT>, which is also a syntax definition and then a <FONT size=2 face="Courier New"><EM>TkEnd</EM></FONT> token. The values of tokens or syntax evaluations can be referenced by prefacing the token with a <FONT size=2><FONT face="Courier New"><EM>&lt;name</EM>&gt;:</FONT></FONT>. The <FONT size=2 face="Courier New"><EM>s:</EM></FONT> is used to reference the value of each statement.</P>
<P>Projections specify how the values parsed from the language input text should appear in the output values. The projection operator <FONT size=2 face="Courier New"><EM>=&gt;</EM></FONT> is used and immediately followed by the pattern we want to use, in place of the default tree structure. In the above <FONT size=2 face="Courier New"><EM>Main </EM></FONT>syntax, the project indicates to write out an entity called <FONT size=2 face="Courier New"><EM>RouterRules</EM></FONT> that contains all the statements that are parsed. Also note the use the <FONT size=2 face="Courier New"><EM>valuesof </EM></FONT>keyword above which pulls the list of values up a level allowing an extra set of braces, that would be generated by default, to be removed.</P>
<P>Next the syntax for Statement is defined which will consist of and if token and a <FONT size=2 face="Courier New"><EM>FilterType</EM></FONT> syntax. The <FONT size=2 face="Courier New"><EM>Statement</EM></FONT> syntax statement looks like this (line 5):</P>
<P><FONT size=2 face="Courier New">syntax Statement = TkIf a:FilterType =&gt; {Filter =&gt; a};</FONT></P>
<P>The <FONT size=2 face="Courier New"><EM>a</EM></FONT> variable is used to store the value of a <FONT size=2 face="Courier New"><EM>FilterType</EM></FONT> which is written out to an Entity called <FONT size=2 face="Courier New"><EM>Filter</EM></FONT>.</P>
<P>Line 33 is one of the more interesting parts of the grammar. This is where the syntax for parsing the URL list is defined. The grammar uses <A href="https://msdn.microsoft.com/en-us/library/dd297491.aspx" mce_href="https://msdn.microsoft.com/en-us/library/dd297491.aspx">Rule Parameters</A> to parse list of definitions. It works sort of like a method call, the Destination syntax takes in destination text and a separator and then splits up the list of URLs based on the separator, projecting each URL out as a value. </P>
<P>The listing below shows the complete “M” output of the example router configuration from Listing 1:</P>
<DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 300px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper>
<DIV style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum1>   1:</SPAN> module Router {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum2>   2:</SPAN>     RouterRules {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum3>   3:</SPAN>         {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum4>   4:</SPAN>             Filter =&gt; {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum5>   5:</SPAN>                 action =&gt; <SPAN style="COLOR: black">"header"</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum6>   6:</SPAN>                 field =&gt; <SPAN style="COLOR: black">"version"</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum7>   7:</SPAN>                 <SPAN style="COLOR: black">operator</SPAN> =&gt; <SPAN style="COLOR: black">"="</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum8>   8:</SPAN>                 fieldvalue =&gt; <SPAN style="COLOR: black">"\"Precise\""</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum9>   9:</SPAN>                 priority =&gt; <SPAN style="COLOR: black">"0"</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum10>  10:</SPAN>                 Destinations =&gt;  {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum11>  11:</SPAN>                     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum12>  12:</SPAN>                         URL =&gt; <SPAN style="COLOR: black">"https://localhost:9090/servicemodelsamples/regularcalc"</SPAN></PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum13>  13:</SPAN>                     }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum14>  14:</SPAN>                 }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum15>  15:</SPAN>             }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum16>  16:</SPAN>         },</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum17>  17:</SPAN>         {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum18>  18:</SPAN>             Filter =&gt; {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum19>  19:</SPAN>                 action =&gt; <SPAN style="COLOR: black">"header"</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum20>  20:</SPAN>                 field =&gt; <SPAN style="COLOR: black">"version"</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum21>  21:</SPAN>                 <SPAN style="COLOR: black">operator</SPAN> =&gt; <SPAN style="COLOR: black">"="</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum22>  22:</SPAN>                 fieldvalue =&gt; <SPAN style="COLOR: black">"\"Rounded\""</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum23>  23:</SPAN>                 priority =&gt; <SPAN style="COLOR: black">""</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum24>  24:</SPAN>                 Destinations =&gt;  {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum25>  25:</SPAN>                     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum26>  26:</SPAN>                         URL =&gt; <SPAN style="COLOR: black">"https://localhost:9091/servicemodelsamples/roundingcalc"</SPAN></PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum27>  27:</SPAN>                     }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum28>  28:</SPAN>                 }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum29>  29:</SPAN>             }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum30>  30:</SPAN>         },</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum31>  31:</SPAN>         {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum32>  32:</SPAN>             Filter =&gt; {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum33>  33:</SPAN>                 action =&gt; <SPAN style="COLOR: black">"endpoint"</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum34>  34:</SPAN>                 <SPAN style="COLOR: black">operator</SPAN> =&gt; <SPAN style="COLOR: black">"="</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum35>  35:</SPAN>                 field =&gt; <SPAN style="COLOR: black">""</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum36>  36:</SPAN>                 fieldvalue =&gt; <SPAN style="COLOR: black">"\"ServiceA\""</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum37>  37:</SPAN>                 priority =&gt; <SPAN style="COLOR: black">""</SPAN>,</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum38>  38:</SPAN>                 Destinations =&gt;  {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum39>  39:</SPAN>                     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum40>  40:</SPAN>                         URL =&gt; <SPAN style="COLOR: black">"https://localhost:9090/servicemodelsamples/regularcalc"</SPAN></PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum41>  41:</SPAN>                     },</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum42>  42:</SPAN>                     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum43>  43:</SPAN>                         URL =&gt; <SPAN style="COLOR: black">"https://localhost:9091/servicemodelsamples/roundingcalc"</SPAN></PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum44>  44:</SPAN>                     }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum45>  45:</SPAN>                 }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum46>  46:</SPAN>             }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum47>  47:</SPAN>         }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum48>  48:</SPAN>     }</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum49>  49:</SPAN> }</PRE><!--CRLF--></DIV></DIV>
<P align=center><B>Listing 3</B></P>
<H3><EM>The Router Model</EM></H3>
<P>In order to process the “M” instance data generated from our language using the “M” tool chain the above a model is needed. The instance data output is too ambiguous for “M” to know how to store it in the Repository database. The “M” language is used to define a schema for the router configurations model. A schema (also referred to as model) in “M” is a definition of a data type, that is, the metadata that describes a type’s mandatory and optional attributes. In database terminology, you can think of a schema as similar to the definition of a table.</P>
<P>In the RouterManager sample the model definition is stored in a file called RouterModel.m. The model is defined as being in the Router module which is the same as the RouterManager grammar and the router configuration instance data shown above.</P>
<P>The router configuration model will have an entity called <FONT size=2 face="Courier New"><EM>RouterRule</EM></FONT> which will have a unique id and a reference to a router filter that makes up the rule. The definition of <FONT size=2 face="Courier New"><EM>RouterRule</EM></FONT> is shown below:</P>
<DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper>
<DIV style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum1>   1:</SPAN> type RouterRule</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum2>   2:</SPAN> {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum3>   3:</SPAN>     Filter : FilterType? where value in FilterTypes;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum4>   4:</SPAN>     id : Integer32 =&gt; AutoNumber();    </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum5>   5:</SPAN> } where identity(id);</PRE><!--CRLF--></DIV></DIV>
<P align=center><B>Listing 4</B></P>
<P>Entities are defined using the <FONT size=2 face="Courier New">type</FONT> keyword. A <FONT size=2 face="Courier New"><EM>FilterType</EM></FONT> entity is defined to for an <I>action </I>which is a text field that holds the name of the type of filter used in the rule. It also contains an optional field that indicated what value should be inspected by a header rule. The operator type is used to specify if the value should be compared as equal or one of the other comparisons (=, contains, startswith, endswith). The <FONT size=2 face="Courier New"><EM>FilterType</EM></FONT> entity has a field called <FONT size=2 face="Courier New"><EM>fieldvalue</EM></FONT>, which contains the value that needs to be matched by the incoming message. The priority field is used to change the order the filter is evaluated. Lastly the <FONT size=2 face="Courier New"><EM>FilterType</EM></FONT> entity has a unique identifier as well as a <FONT size=2 face="Courier New"><EM>Destinations</EM></FONT> field that contains a reference to one or more destination entities.</P>
<P>The listing for <FONT size=2 face="Courier New"><EM>FilterType</EM></FONT> is shown below:</P>
<DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper>
<DIV style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum1>   1:</SPAN> type FilterType</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum2>   2:</SPAN> {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum3>   3:</SPAN>     id : Integer32 =&gt; AutoNumber();    </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum4>   4:</SPAN>     action: Text(20);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum5>   5:</SPAN>     field: Text?;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum6>   6:</SPAN>     <SPAN style="COLOR: black">operator</SPAN> : Text;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum7>   7:</SPAN>     fieldvalue: Text;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum8>   8:</SPAN>     priority: Text;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum9>   9:</SPAN>     Destinations : {(DestinationType where value in DestinationList)*};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum10>  10:</SPAN> } where identity(id);</PRE><!--CRLF--></DIV></DIV>
<P align=center><B>Listing 5</B></P>
<P>The <FONT size=2 face="Courier New"><EM>DestinationType</EM></FONT> entity is used to store a URL of an endpoint to send messages to. Each filter has one or more URLs that a message can be delivered to. The <FONT size=2 face="Courier New"><EM>DestinationType</EM></FONT> entity has a unique id and a text field to store the URL. The Listing for<FONT size=2 face="Courier New"><EM> DestinationType</EM></FONT> is shown below:</P>
<DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper>
<DIV style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum1>   1:</SPAN> type DestinationType </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum2>   2:</SPAN> {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum3>   3:</SPAN>     id : Integer32 =&gt; AutoNumber();</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum4>   4:</SPAN>     URL : Text;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum5>   5:</SPAN> } where identity(id);</PRE><!--CRLF--></DIV></DIV>
<P align=center><B>Listing 6</B></P>
<P>Note: The RouterManager grammar supports multiple operators, but the RouterManager runtime only supports the “=” operator. The other operators are left as an implementation exercise if the functionality is desired.</P>
<P>Type statements indicate what a model schema should look like but does not convey how it should be stored. Extents are used to specify how the entities are stored. The RouterModel defines three extents one for each of the types. <FONT size=2><FONT face="Courier New"><EM>DestinationList</EM> </FONT></FONT>holds zero or more <FONT size=2 face="Courier New"><EM>DestinationTypes</EM></FONT>, denoted by using the <FONT size=2 face="Courier "><EM>*</EM></FONT> operator. <FONT size=2 face="Courier New"><EM>FilterTypes </EM></FONT>holds <FONT size=2 face="Courier New"><EM>FilterType</EM></FONT> entities and <FONT size=2><FONT face="Courier New"><EM>RouterRules</EM> </FONT></FONT>hold <FONT size=2 face="Courier New"><EM>RouterRule</EM></FONT> entities</P>
<P>The complete listing of the RouterModel.m file is show below:</P>
<DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper>
<DIV style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum1>   1:</SPAN> module Router{</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum2>   2:</SPAN>     type DestinationType </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum3>   3:</SPAN>     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum4>   4:</SPAN>         id : Integer32 =&gt; AutoNumber();</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum5>   5:</SPAN>         URL : Text;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum6>   6:</SPAN>     } where identity(id);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum7>   7:</SPAN>     </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum8>   8:</SPAN>     type FilterType</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum9>   9:</SPAN>     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum10>  10:</SPAN>         id : Integer32 =&gt; AutoNumber();    </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum11>  11:</SPAN>         action: Text(20);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum12>  12:</SPAN>         field: Text?;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum13>  13:</SPAN>         <SPAN style="COLOR: black">operator</SPAN> : Text;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum14>  14:</SPAN>         fieldvalue: Text;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum15>  15:</SPAN>         priority: Text;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum16>  16:</SPAN>         Destinations : {(DestinationType where value in DestinationList)*};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum17>  17:</SPAN>     } where identity(id);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum18>  18:</SPAN>     </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum19>  19:</SPAN>     type RouterRule</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum20>  20:</SPAN>     {</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum21>  21:</SPAN>         Filter : FilterType? where value in FilterTypes;</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum22>  22:</SPAN>         id : Integer32 =&gt; AutoNumber();    </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum23>  23:</SPAN>     } where identity(id);</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum24>  24:</SPAN>     </PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum25>  25:</SPAN>     DestinationList : {DestinationType*};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum26>  26:</SPAN>     FilterTypes : {FilterType*};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: white; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum27>  27:</SPAN>     RouterRules:{RouterRule*};</PRE><!--CRLF--><PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px"><SPAN style="COLOR: #606060" id=lnum28>  28:</SPAN> }</PRE><!--CRLF--></DIV></DIV>
<P align=center><B>Listing 4</B></P>
<P><B>Note:</B> There is an easy way to see if your language output maps to your model. In “Intellipad” load up your “M” model definition and paste in some “M” instance data generated from the language input text (see <STRONG>Listing 3</STRONG>). “Intellipad” will show error where the instance data doesn’t match the model. You can then change the model to better match the instance data or figure out how to change your projections in the grammar to match the model. In the RouterManager sample, if you have run the redeploy_router.bat file successfully, you should see a file called Router.m that contains the sample configuration instance data. Copy one of the RouterRules entity data to the clipboard and then load the RouterModel.m file into “Intellipad”. Insert the copied RouterRules entity from the clipboard below the RouteRules extent definition. In the “Intellipad” “M Mode” menu, choose “T-SQL Preview”. It should show the T-SQL in a second window with no errors as the grammar output matches the model. <STRONG>Image 2</STRONG> below is a screen shot of the RouterModel with a RouterRules entity data inserted in “Intellipad” (notice the <FONT size=2 face="Courier New"><EM>RouterRules</EM></FONT> data highlighted at the bottom):</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_9.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_9.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_9.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_thumb_3.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_thumb_3.png" width=519 height=422 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_9945/image_thumb_3.png"></A> </P>
<P align=center><B>Image 2</B></P>
<H3>Conclusion</H3>
<P>As you can see, it is very easy to define domain-specific languages and data models using the SQL Server Modeling CTP. By combining the two, it gives you the foundation to make powerful model driven applications. Part III of the “Model Driven Content Based Routing using the SQL Server Modeling CTP” will cover the RouterManager runtime and how it uses the model and model data for message routing. </P>]]></content:encoded>
    </item>
    <item>
      <title>Welcome to the SQL Server Data and Modeling Customer Advisory Team (DM CAT) blog</title>
      <link>https://docs.microsoft.com/archive/blogs/dmcat/welcome-to-the-sql-server-data-and-modeling-customer-advisory-team-dm-cat-blog</link>
      <pubDate>Mon, 16 Nov 2009 15:56:00 GMT</pubDate>
      <dc:creator><![CDATA[dkaufman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmcat/2009/11/16/welcome-to-the-sql-server-data-and-modeling-customer-advisory-team-dm-cat-blog/</guid>
      <description><![CDATA[Welcome to the SQL Server Data and Modeling Customer Advisory Team (DM CAT) blog. Our team assists...]]></description>
      <content:encoded><![CDATA[<P>Welcome to the SQL Server Data and Modeling Customer Advisory Team (DM CAT) blog. Our team assists customers in adopting Microsoft’s <A href="https://msdn.microsoft.com/data" mce_href="https://msdn.microsoft.com/data">Data&nbsp;Development Technology</A> and shares the knowledge we gain with the rest of the Microsoft community. You can look forward to seeing posts offering guidance and best practices on a variety of Microsoft technology including <A href="https://msdn.microsoft.com/en-us/oslo/default.aspx" mce_href="https://msdn.microsoft.com/en-us/oslo/default.aspx">SQL Server Modeling</A>, <A href="https://msdn.microsoft.com/en-us/library/bb399572(VS.100).aspx" mce_href="https://msdn.microsoft.com/en-us/library/bb399572(VS.100).aspx">Entity Framework</A> and <A href="https://msdn.microsoft.com/en-us/library/cc668792(VS.100).aspx" mce_href="https://msdn.microsoft.com/en-us/library/cc668792(VS.100).aspx">Data Services</A>, as well as insight on how the Data and Modeling technologies can be used with other Microsoft products.</P>
<P>The members of our team include:</P>
<P>Dana Kaufman – Program Manager <BR>James Podgorski – Program Manager <BR>Jaime Alva Bravo – Program Manager</P>]]></content:encoded>
    </item>
    <item>
      <title>Model Driven Content Based Routing using SQL Server Modeling CTP – Part I</title>
      <link>https://docs.microsoft.com/archive/blogs/dmcat/model-driven-content-based-routing-using-sql-server-modeling-ctp-part-i</link>
      <pubDate>Mon, 16 Nov 2009 15:39:00 GMT</pubDate>
      <dc:creator><![CDATA[dkaufman]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmcat/2009/11/16/model-driven-content-based-routing-using-sql-server-modeling-ctp-part-i/</guid>
      <description><![CDATA[Author: Dana Kaufman
Reviewers: James Podgorski, Jaime Alva Bravo, Chris Sells, Matthew Snider,...]]></description>
      <content:encoded><![CDATA[<P>Author: Dana Kaufman</P>
<P>Reviewers: James Podgorski, Jaime Alva Bravo, Chris Sells, Matthew Snider, David Miller, Scott Roberts</P>
<H3>Introduction</H3>
<P>One of the major new WCF features in .NET 4 is the <A href="https://msdn.microsoft.com/en-us/library/ee517422(VS.100).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ee517422(VS.100).aspx">Routing Service</A> which is a configurable WCF-based service that supports content-based routing and protocol bridging. The content based routing capability in .NET 4 allows for WCF to perform message filtering based on content contained in either the SOAP headers or within the message body. For instance, if a company has two different versions of the same service deployed, the client application can call into a central routing service. The routing service can then forward the message to the correct backend service based on information it extracts from the incoming message, such as version number. The routing service also supports error handling routing that can automatically resend the message to another destination endpoint in the event of an error.</P>
<P>Unfortunately, the default routing service is not the easiest to manage or configure. Fortunately, the recently released SQL Server Modeling CTP makes it easy to build model driven application and the .NET 4 router configuration is a good modeling candidate. As such, the <A href="https://code.msdn.microsoft.com/RouterManager" mce_href="https://code.msdn.microsoft.com/RouterManager">RouterManager</A> sample which is available for <A href="https://code.msdn.microsoft.com/RouterManager" mce_href="https://code.msdn.microsoft.com/RouterManager">download</A> from MSDN Code Gallery, shows how this can be accomplished using <A href="https://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx" mce_href="https://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx">Visual Studio 2010 Beta 2</A> and the <A href="https://msdn.microsoft.com/en-us/oslo/default.aspx" mce_href="https://msdn.microsoft.com/en-us/oslo/default.aspx">SQL Server Modeling CTP</A> which was released in conjunction with <A href="https://microsoftpdc.com/" mce_href="https://microsoftpdc.com/">PDC09</A>. This is the first in a series of articles that will cover the architecture and concepts used in the RouterManager sample application to create a fully model driven content based router.</P>
<P>The SQL Server Modeling CTP can be used to create a domain specific language (DSL) that can make the routing configuration of the WCF routing service much simpler. This is accomplished by first defining a language that is human readable, which will provide IT Operations and others within an organization who are <B>not</B> expert developers with an easier way to interact with applications. The CTP’s modeling language features make it easy to define the structure of the configuration data in a human readable representation that can be shared within an application’s modules, tiers and tools or between even between applications. Also included, as part of the CTP, is the SQL Server Modeling Services, which provides functionality to store, access and share both the physical and metadata representation of the model. The Modeling CTP also provides a visual tool called “Quadrant” for viewing and interacting with models and model data.</P>
<H3>The Application</H3>
<P>Looking at the .NET 4 WCF Routing service, the out of the box way to configure the routing behavior is by editing the XML in the App.config file. Instances of the Routing Service have filters applied to them which are the rules used to inspect the message and determine the message destination. Below is a sample router rules configuration from as it would appear in an App.config file:</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">routing</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  <SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">filters</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">    <SPAN style="COLOR: #008000">&lt;!--define the different message filters--&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">    <SPAN style="COLOR: #008000">&lt;!--define an xpath message filters to look for the custom header coming from the client--&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">    <SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">filter</SPAN> <SPAN style="COLOR: #ff0000">name</SPAN>=<SPAN style="COLOR: #0000ff">"XPathFilter"</SPAN> <SPAN style="COLOR: #ff0000">filterType</SPAN>=<SPAN style="COLOR: #0000ff">"XPath"</SPAN> <SPAN style="COLOR: #ff0000">filterData</SPAN>=<SPAN style="COLOR: #0000ff">"/s12:Envelope/s12:Header/version = Precise"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">    <SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">filter</SPAN> <SPAN style="COLOR: #ff0000">name</SPAN>=<SPAN style="COLOR: #0000ff">"XPathFilter1"</SPAN> <SPAN style="COLOR: #ff0000">filterType</SPAN>=<SPAN style="COLOR: #0000ff">"XPath"</SPAN> <SPAN style="COLOR: #ff0000">filterData</SPAN>=<SPAN style="COLOR: #0000ff">"/s12:Envelope/s12:Header/version = Rounded"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">    <SPAN style="COLOR: #008000">&lt;!--define an endpoint name filter looking for messages that show up on the virtual regular calculator endpoint--&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">    <SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">filter</SPAN> <SPAN style="COLOR: #ff0000">name</SPAN>=<SPAN style="COLOR: #0000ff">"EndpointNameFilter"</SPAN> <SPAN style="COLOR: #ff0000">filterType</SPAN>=<SPAN style="COLOR: #0000ff">"EndpointName"</SPAN> <SPAN style="COLOR: #ff0000">filterData</SPAN>=<SPAN style="COLOR: #0000ff">“ServiceA</SPAN>"/&gt;</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  &lt;/<SPAN style="COLOR: #ff0000">filters</SPAN>&gt;</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  &lt;<SPAN style="COLOR: #ff0000">filterTables</SPAN>&gt;</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">    &lt;<SPAN style="COLOR: #ff0000">filterTable</SPAN> <SPAN style="COLOR: #ff0000">name</SPAN>=<SPAN style="COLOR: #0000ff">"filterTable1"</SPAN>&gt;</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">      &lt;!--<SPAN style="COLOR: #ff0000">add</SPAN> <SPAN style="COLOR: #ff0000">the</SPAN> <SPAN style="COLOR: #ff0000">filters</SPAN> <SPAN style="COLOR: #ff0000">to</SPAN> <SPAN style="COLOR: #ff0000">the</SPAN> <SPAN style="COLOR: #ff0000">message</SPAN> <SPAN style="COLOR: #ff0000">filter</SPAN> <SPAN style="COLOR: #ff0000">table</SPAN>--&gt;</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">      &lt;!--<SPAN style="COLOR: #ff0000">first</SPAN> <SPAN style="COLOR: #ff0000">look</SPAN> <SPAN style="COLOR: #ff0000">for</SPAN> <SPAN style="COLOR: #ff0000">the</SPAN> <SPAN style="COLOR: #ff0000">custom</SPAN> <SPAN style="COLOR: #ff0000">header</SPAN>, <SPAN style="COLOR: #ff0000">and</SPAN> <SPAN style="COLOR: #ff0000">if</SPAN> <SPAN style="COLOR: #ff0000">we</SPAN> <SPAN style="COLOR: #ff0000">find</SPAN> <SPAN style="COLOR: #ff0000">it</SPAN>, <SPAN style="COLOR: #ff0000">send</SPAN> <SPAN style="COLOR: #ff0000">the</SPAN> <SPAN style="COLOR: #ff0000">message</SPAN> <SPAN style="COLOR: #ff0000">to</SPAN> <SPAN style="COLOR: #ff0000">the</SPAN> <SPAN style="COLOR: #ff0000">rounding</SPAN> <SPAN style="COLOR: #ff0000">calc</SPAN> <SPAN style="COLOR: #ff0000">endpoint</SPAN>--&gt;</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">      &lt;<SPAN style="COLOR: #ff0000">add</SPAN> <SPAN style="COLOR: #ff0000">filterName</SPAN>=<SPAN style="COLOR: #0000ff">"XPathFilter"</SPAN> <SPAN style="COLOR: #ff0000">endpointName</SPAN>=<SPAN style="COLOR: #0000ff">"roundingCalcEndpoint"</SPAN> <SPAN style="COLOR: #ff0000">priority</SPAN>=<SPAN style="COLOR: #0000ff">“0</SPAN>"<SPAN style="COLOR: #0000ff">/&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">      <SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">add</SPAN> <SPAN style="COLOR: #ff0000">filterName</SPAN>=<SPAN style="COLOR: #0000ff">"XPathFilter1"</SPAN> <SPAN style="COLOR: #ff0000">endpointName</SPAN>=<SPAN style="COLOR: #0000ff">“regularCalcEndpoint</SPAN>" <SPAN style="COLOR: #ff0000">priority</SPAN>=<SPAN style="COLOR: #0000ff">“1</SPAN>"<SPAN style="COLOR: #0000ff">/&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">      <SPAN style="COLOR: #008000">&lt;!--if the header wasn't there, send the message based on which virtual endpoint it arrived at--&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">      <SPAN style="COLOR: #008000">&lt;!--we determine this through the endpoint name, or through the address prefix--&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">      <SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">add</SPAN> <SPAN style="COLOR: #ff0000">filterName</SPAN>=<SPAN style="COLOR: #0000ff">"EndpointNameFilter"</SPAN> <SPAN style="COLOR: #ff0000">endpointName</SPAN>=<SPAN style="COLOR: #0000ff">"regularCalcEndpoint"</SPAN> <SPAN style="COLOR: #ff0000">priority</SPAN>=<SPAN style="COLOR: #0000ff">"1"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN></PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">      <SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">add</SPAN> <SPAN style="COLOR: #ff0000">filterName</SPAN>=<SPAN style="COLOR: #0000ff">"EndpointNameFilter"</SPAN> <SPAN style="COLOR: #ff0000">endpointName</SPAN>=<SPAN style="COLOR: #0000ff">"roundingCalcEndpoint"</SPAN> <SPAN style="COLOR: #ff0000">priority</SPAN>=<SPAN style="COLOR: #0000ff">“1</SPAN>"/&gt;</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">    &lt;/<SPAN style="COLOR: #ff0000">filterTable</SPAN>&gt;</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  &lt;/<SPAN style="COLOR: #ff0000">filterTables</SPAN>&gt;</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">&lt;/<SPAN style="COLOR: #ff0000">routing</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN></PRE></PRE>
<P align=center><B>Listing 1</B></P>
<P>This configuration defines three <I>router filters</I>. A router filter is a rule the router uses to evaluate and take action on a message. The first filter rule instructs the router to the look for “version” element in the SOAP header with a value of “Precise”; if the router finds a match, it forwards the message to the regular calculator service via an endpoint called “regularCalcEndpoint” which is defined elsewhere in the App.config. The second filter rule indicates if the SOAP header “version” contains a value of “Rounded” then send the message to the rounding calculator service. The last router filter indicates if the message arrives on an endpoint named “ServiceA” then send it to the regular calculator service and if that service is unavailable, send it to the rounding calculator service.</P>
<P>The routing configuration in Listing 1 is very complex, requiring the person maintaining the configuration to understand and modify multiple sections of the XML contained in the App.config file. Creating a language specifically for the task of router configuration could make this much easier. The example listing below shows the same router configurations but implemented in a router DSL:</P>
<P mce_keep="true">&nbsp;</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">router begin</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  if header version = "Precise" priority 0 destination https://localhost:9090/regularcalc</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  if header version = "Rounded" destination https://localhost:9091/roundingcalc</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  if endpoint = "ServiceA" destination https://localhost:9090/regularcalc, https://localhost:9091/roundingcalc</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">end</PRE></PRE>
<P align=center><B>Listing 2</B><B></B></P>
<P>As you can see, this is a much simpler syntax. The router language uses “if” statements to specify each filter. Each if statement also contains a destination section requiring only a single line for each rule instead of requiring the editing of multiple sections in the XML as in the above example.</P>
<H4>Architecture</H4>
<P>The RouterManager sample implements the above router language using the SQL Server Modeling CTP grammar support. The rules configuration data is modeled by using the “M” language. The CTP toolchain is used by the RouterManager to compile the DSL configuration information into Router configuration model instance data, which is stored in a Repository database hosted on SQL Server. The RouterManager runtime knows how to load router rules from the Repository database. Lastly, the “Quadrant” tool can be used to view and interact with the Router configuration data contained in the Repository. A diagram of the RouterManager sample architecture is shown below:</P>
<P align=center><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_2.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_thumb.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_thumb.png" width=509 height=348 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_thumb.png"></A> </P>
<P align=center><STRONG>Diagram 1</STRONG></P>
<H4>Implementation</H4>
<P>Imagine a company deploys a financial calculation service that is used by a number of departments. After the service is in use for a while, they realize that they can optimize the processing by rounding the results. They don’t want to disturb the existing applications that require very specific types of results; so instead they simply roll out a second service that implements the new logic. The company then deploys the .NET 4 WCF routing service to receive both the old and new incoming messages from the client applications and based the message header, routes the messages to the correct version of the backend service.</P>
<P>The RouterManager sample simulates the above example. The sample consists of the RouterManager executable host written in C#, which is an implementation of the WCF Routing Service that knows how to load the Router configuration from the Repository. At startup it opens up a Routing Service host that listens for incoming messages to forward to the correct remote endpoint based on its configuration. RouterManager also has a controller interface exposed as a second host endpoint that is used for remotely configuring the router.</P>
<P>The sample project also contains a pair of example webservices that implement a simple calculator which exposes methods for add, subtract, multiply and divide. One instance of the web service returns regular calculated results while the second instance returns rounded results. </P>
<P>A test client is also included that can be used to send messages with different configuration, through the router to the backend services and displays the results. For instance, it can set the SOAP header “version” to a value that the router will then inspect and send to the appropriate calculator service. The test client also contains a tab that can be used to edit router configurations and send the new instructions to the router controller. When the router controller receives new configurations, it converts the input text into configuration data which is turned into SQL and pushed into the Repository database. The controller has a second operation which is used to signal the RouterManager to reload the Routing Service router rules from the Repository database. An image of the RouterManager sample in the Visual Studio Solution Explorer is shown below:</P>
<P align=center><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_6.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_6.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_6.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_thumb_2.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_thumb_2.png" width=178 height=256 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_thumb_2.png"></A>&nbsp;</P>
<P align=center><STRONG>Image 1</STRONG></P>
<H4>Running the RouterManager:</H4>
<P>1. Load the RouterManager.sln solution in Visual Studio 2010 Beta 2. </P>
<P>2. Edit the redeploy_router.bat file in the RouterModel project to make sure the path to the SQL Server Modeling CTP bin directory is set properly.</P>
<P>3. Build the RouterManager solution.</P>
<P>4. Open a Command Prompt and go to RouterModel\bin\Debug directory of the solution. Execute the redeploy_router.bat file. This will use our Router grammar to parse the Router filter rules sample instance data contained in the file Router.txt and generate a Router.m file which will then compile and install the resulting image into the repository. The following schemas should then be visible in SQL Server Management Studio within the Repository database: Router.RouterRules, Router.FilterTypes, Router.FilterTypes.Destinations, and Router.DestinationList. The code name "Quadrant" modeling tool can also be used to explore the repository for these models. <BR><STRONG>Note:</STRONG> Ignore any M6010 or M6046 warnings. The M6010 warnings occur the first time the redeploy_router.bat file is run because the Router model and instance data has not yet been installed. </P>
<P>5. Run the four projects executables by pressing the “Start Debugging” button which will start all of the executables.</P>
<P>A screenshot of the running applications are shown below:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_10.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_10.png" mce_href="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_10.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_thumb_4.png" original-url="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_thumb_4.png" width=563 height=398 mce_src="https://blogs.msdn.com/blogfiles/dmcat/WindowsLiveWriter/ModelDrivenContentBasedRoutingusingSQLSe_F962/image_thumb_4.png"></A> </P>
<P align=center><STRONG>Image 2</STRONG></P>
<P>By default, the RouterMananager loads up configured similar to the example routing rules specified above in Listing 2. The RouterManager can be tested using the Router Test Client. Press the “Call Services” button to send SOAP message for the Add operation to the Calculator service which includes a header named “version” with a value of “Precise”. After a second, a result of “Result = 3.579” should be displayed in the Response tab. The RouterManager forwarded the message to the regular calculator. Next select the “Add Header version = “Rounded”” radio button and press “Call Services” again. This time, the Response window will have “Result = 3.6” because the RouterManager forwarded the message to the Rounding calculator service.</P>
<P>Click on the “Configure Router” tab and the current set of Router rules will be displayed. Change the text in the first rule version = “Precise” to version =”Rounded” and the text in the second rule from version =”Rounded” to version = “Precise”.</P>
<P>The full text of the router rules should look like this:</P><PRE style="BORDER-BOTTOM: #cecece 1px solid; BORDER-LEFT: #cecece 1px solid; PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #fbfbfb; MIN-HEIGHT: 40px; PADDING-LEFT: 5px; WIDTH: 650px; PADDING-RIGHT: 5px; OVERFLOW: auto; BORDER-TOP: #cecece 1px solid; BORDER-RIGHT: #cecece 1px solid; PADDING-TOP: 5px"><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">router begin</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  if header version = "Rounded" priority 0 destination https://localhost:9090/servicemodelsamples/regularcalc</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  if header version = "Precise" destination https://localhost:9091/servicemodelsamples/roundingcalc</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  if endpoint = "ServiceA" destination https://localhost:9090/servicemodelsamples/regularcalc, https://localhost:9091/servicemodelsamples/roundingcalc</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">end</PRE></PRE>
<P align=center><STRONG>Listing 3</STRONG></P>
<P>Press the “Configure Router” button and a new console will appear as the SQL Server Modeling CTP processes the router configuration information, generates new instance data for the model and loads the new configuration into the Repository (this will be covered in-depth in Part II). </P>
<P>The new router rules should be ready. Click on the “Test Service” tab to display the web service testing interface. Select the “Add Header version = “Precise”” radio button and press “Call Services” again. Then press the “Call Service” button on the Router Test Client. The Response window will display “Result = 3.6” indicating that the Rounding calculator service was called this time based on the updated routing rules.</P>
<P>The RouterManager sample supports five different routing filters. The table below lists the supported filters and describes their use: 
<TABLE border=1 cellSpacing=0 cellPadding=0>
<TBODY>
<TR>
<TD vAlign=top width=146>
<P><B><U>Filter</U></B></P></TD>
<TD vAlign=top width=812>
<P><B><U>Description</U></B></P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>header</P></TD>
<TD vAlign=top width=812>
<P>Message contains a SOAP header with a specific value(supports SOAP 1.1 and 1.2 envelopes)</P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>endpoint</P></TD>
<TD vAlign=top width=812>
<P>Message arrives on a specific endpoint</P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>address</P></TD>
<TD vAlign=top width=812>
<P>Message arrives on a specific address</P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>addressprefix</P></TD>
<TD vAlign=top width=812>
<P>Message arrives on an address that contains the specified prefix</P></TD></TR>
<TR>
<TD vAlign=top width=146>
<P>matchall</P></TD>
<TD vAlign=top width=812>
<P>Any message</P></TD></TR></TBODY></TABLE></P>
<P>To configure the RouterManager via the router language, the RouterManager exposes a controller service defined by the IRoutingController. The definition of the IRoutingController interface is shown below:</P><PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"><SPAN style="COLOR: #0000ff">public</SPAN> <SPAN style="COLOR: #0000ff">interface</SPAN> IRoutingController</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">{</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  [OperationContract]</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  <SPAN style="COLOR: #0000ff">void</SPAN> RefreshRouterFilters();</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px"></PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  [OperationContract]</PRE><PRE style="BACKGROUND-COLOR: #fbfbfb; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">  <SPAN style="COLOR: #0000ff">void</SPAN> BuildRoutingModel(String rm);</PRE><PRE style="BACKGROUND-COLOR: #ffffff; MARGIN: 0em; WIDTH: 100%; FONT-FAMILY: consolas,'Courier New',courier,monospace; FONT-SIZE: 12px">}</PRE></PRE>
<P align=center><STRONG>Listing 4</STRONG></P>
<P>The controller has two operations. The BuildRoutingModel() takes in a string that contains the new routing configuration and uses the SQL Server Modeling CTP to turn the configuration into Router Model instance data and insert the new configuration into the SQL Server Model Services enabled Repository database. (How this works using the SQL Server Modeling CTP tool chain will be covered in depth in Part II). <BR>The second controller method, RefreshRouterRules(), leverages the <A href="https://msdn.microsoft.com/en-us/library/bb399572(VS.100).aspx" mce_href="https://msdn.microsoft.com/en-us/library/bb399572(VS.100).aspx">Entity Framework</A> to query the Repository for the latest router rules. It then builds a set of router filters based on the rules and re-programs the Routing Service with the new instructions. The .NET WCF Routing Service has a special method called ApplyConfiguration() which takes in a new set of router configurations and applies them to the Routing Service without the need to take down the routing service listener. Any messages in flight before the call to ApplyConfiguration() will be processed by the old configuration and any messages sent from new connection to the router service will be processed with the new router configuration. The implementation of RefreshRouterRules() makes use of this method to swap in the new router configuration on the fly without dropping messages.</P>
<P>On the test client, clicking “Configure Router” causes the client to first call the BuildRoutingModel(), passing the configuration text. When that operation complete the test client then calls the RefreshRouterRules() operation to inform the RouterManger to reload the router rules from the Repository database.</P>
<P><B>Note:</B> The routing control interface is split into two different operations to decouple the insertion of new configuration data into the Repository from the re-loading of the rules into the Routing Service. In real world scenarios multiple instances of the RouterManager would probably be deployed. The configuration of the router to the Repository could be done in one step and then use technology such as&nbsp;<A href="https://msdn.microsoft.com/en-us/library/ms130764.aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms130764.aspx">SQL Server Query Notifications</A> in conjunction with the RefreshRouterRules() operation.&nbsp; When leveraged in this way the database could signal to multiple router the to re-load their router rules.</P>
<P>The controller host endpoint is defined via the WCF configuration information specified in the RouterManager project’s App.config file. This offers the flexibility of allowing the Router controller host configuration to be modified to add WCF security or changed the protocol binding used by the Router controller through the App.config.</P>
<H4>Conclusion</H4>
<P>That concludes the overview of the RouterManager sample application. Combining the SQL Server Modeling CTP and the .NET 4 Routing Service makes any easy to use, model driven solution for content based routing of WCF messages. Part II of the “Model Driven Content Based Routing” will cover the Router model and Router language definitions as well as how they are used with the SQL Server Modeling CTP.</P>]]></content:encoded>
    </item>
  </channel>
</rss>