<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>[Giagnocavo]Michael::Write()</title>
    <link>http://www.atrevido.net/blog/</link>
    <description>Something about .NET.</description>
    <copyright>Michael Giagnocavo</copyright>
    <lastBuildDate>Thu, 26 Jun 2008 06:15:10 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.7174.0</generator>
    <managingEditor>mggUNSPAM@telefinity.com</managingEditor>
    <webMaster>mggUNSPAM@telefinity.com</webMaster>
    <item>
      <trackback:ping>http://www.atrevido.net/blog/Trackback.aspx?guid=ae23e7f3-a43e-4bc5-90cc-12b2b74dff99</trackback:ping>
      <pingback:server>http://www.atrevido.net/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.atrevido.net/blog/PermaLink,guid,ae23e7f3-a43e-4bc5-90cc-12b2b74dff99.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.atrevido.net/blog/CommentView,guid,ae23e7f3-a43e-4bc5-90cc-12b2b74dff99.aspx</wfw:comment>
      <wfw:commentRss>http://www.atrevido.net/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=ae23e7f3-a43e-4bc5-90cc-12b2b74dff99</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In my <a href="http://www.atrevido.net/blog/2008/06/26/LINQ+To+The+CRUD+CreateTable+Generator+In+F.aspx">last
post</a>, I said I'd write the sample in C# to compare to F#. Well, I grossly underestimated
the power of query comprehensions. The C# version is almost the same length (formatting
differences, mainly). I'm surprised and impressed. (Or maybe I'm writing F# like I'd
write C#.) Edit: I think maybe sequence expressions could cut it down a bit...
</p>
        <p>
...But... C# still can't do discriminated unions efficiently or effectively ;). 
</p>
        <p>
          <hr />
        </p>
        <p>
        </p>
        <div style="FONT-SIZE: 11pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: Consolas">
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    1</span> <span style="COLOR: green">//
crudcreatecompare.cs: Generates LINQ CRUD table fields using the horribly named DatabaseBase
code</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    2</span> <span style="COLOR: green">//</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    3</span> <span style="COLOR: green">//
Tables look like: [Table(Name="dbo.Accounts")]</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    4</span> <span style="COLOR: green">//
Columns look like this:</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    5</span> <span style="COLOR: green">// 
[Column(Storage="_AccountName", DbType="VarChar(128) NOT NULL", CanBeNull=false, IsPrimaryKey=true)]</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    6</span> <span style="COLOR: green">// 
[DataMember(Order=1)] // Exists if serialization is turned on; used to order key parameters</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    7</span> <span style="COLOR: green">//
Emits:</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    8</span> <span style="COLOR: green">// 
public static readonly TableHelper&lt;Account, String&gt; Accounts =</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    9</span> <span style="COLOR: green">//   
  CreateTable(dc =&gt; dc.Accounts, a =&gt; a.AccountName);</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   10</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   11</span> <span style="COLOR: blue">using</span> System;
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   12</span> <span style="COLOR: blue">using</span> System.Collections.Generic;
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   13</span> <span style="COLOR: blue">using</span> System.Data.Linq.Mapping;
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   14</span> <span style="COLOR: blue">using</span> System.IO;
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   15</span> <span style="COLOR: blue">using</span> System.Linq;
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   16</span> <span style="COLOR: blue">using</span> System.Reflection;
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   17</span> <span style="COLOR: blue">using</span> System.Runtime.Serialization;
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   18</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   19</span> <span style="COLOR: blue">class</span><span style="COLOR: #2b91af">Program</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   20</span> {
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   21</span>     <span style="COLOR: blue">static</span><span style="COLOR: blue">void</span> Main()
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   22</span>     {
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   23</span>         <span style="COLOR: #2b91af">Console</span>.WriteLine(
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   24</span>        
    <span style="COLOR: blue">new</span><span style="COLOR: #2b91af">Program</span>().generate(
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   25</span>        
    <span style="COLOR: #a31515">"C:\\yourlinq.dll"</span>));
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   26</span>     }
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   27</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   28</span>     <span style="COLOR: blue">string</span> generate(<span style="COLOR: blue">string</span> asmpath)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   29</span>     {
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   30</span>         <span style="COLOR: blue">var</span> asm
= <span style="COLOR: #2b91af">Assembly</span>.LoadFrom(asmpath);
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   31</span>         <span style="COLOR: blue">var</span> lines
= <span style="COLOR: blue">from</span> t <span style="COLOR: blue">in</span> asm.GetExportedTypes()
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   32</span>        
            <span style="COLOR: blue">let</span> ta
= getAttr&lt;<span style="COLOR: #2b91af">TableAttribute</span>&gt;(t)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   33</span>        
            <span style="COLOR: blue">where</span> ta
!= <span style="COLOR: blue">null</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   34</span>        
            <span style="COLOR: blue">let</span> name
= pluralize(ta.Name.Replace(<span style="COLOR: #a31515">"dbo."</span>, <span style="COLOR: #a31515">""</span>))
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   35</span>        
            <span style="COLOR: blue">orderby</span> name
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   36</span>        
            <span style="COLOR: blue">select</span> genTable(t,
name);
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   37</span>         <span style="COLOR: blue">return</span> joinStrings(<span style="COLOR: #a31515">""</span>,
lines);
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   38</span>     }
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   39</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   40</span>     <span style="COLOR: blue">string</span> genTable(<span style="COLOR: #2b91af">Type</span> t, <span style="COLOR: blue">string</span> tableName)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   41</span>     {
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   42</span>         <span style="COLOR: blue">var</span> keyProps
=
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   43</span>        
    <span style="COLOR: blue">from</span> p <span style="COLOR: blue">in</span> t.GetProperties()
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   44</span>        
    <span style="COLOR: blue">let</span> c = getAttr&lt;<span style="COLOR: #2b91af">ColumnAttribute</span>&gt;(p)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   45</span>        
    <span style="COLOR: blue">where</span> c != <span style="COLOR: blue">null</span> &amp;&amp;
c.IsPrimaryKey
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   46</span>        
    <span style="COLOR: blue">let</span> dm = getAttr&lt;<span style="COLOR: #2b91af">DataMemberAttribute</span>&gt;(p)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   47</span>        
    <span style="COLOR: blue">orderby</span> dm == <span style="COLOR: blue">null</span> ?
0 : dm.Order
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   48</span>        
    <span style="COLOR: blue">select</span> p;
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   49</span>         <span style="COLOR: blue">var</span> tw
= <span style="COLOR: blue">new</span><span style="COLOR: #2b91af">StringWriter</span>();
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   50</span>        
tw.WriteLine(<span style="COLOR: #a31515">"public static readonly TableHelper&lt;{0},
{1}&gt; {2} ="</span>,
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   51</span>        
    t.Name,
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   52</span>        
    joinStrings(<span style="COLOR: #a31515">", "</span>, keyProps.Select(p
=&gt; p.PropertyType.Name)),
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   53</span>        
    tableName);
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   54</span>        
tw.WriteLine(<span style="COLOR: #a31515">"\tCreateTable(dc =&gt; dc.{0}, {1});"</span>,
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   55</span>        
    tableName,
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   56</span>        
    joinStrings(<span style="COLOR: #a31515">", "</span>, keyProps.Select(p
=&gt; <span style="COLOR: #a31515">"a =&gt; a."</span> + p.Name)));
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   57</span>        
tw.WriteLine();
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   58</span>         <span style="COLOR: blue">return</span> tw.ToString();
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   59</span>     }
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   60</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   61</span>     <span style="COLOR: blue">string</span> joinStrings(<span style="COLOR: blue">string</span> sep, <span style="COLOR: #2b91af">IEnumerable</span>&lt;<span style="COLOR: blue">string</span>&gt;
items)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   62</span>     {
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   63</span>         <span style="COLOR: blue">return</span><span style="COLOR: blue">string</span>.Join(sep,
items.ToArray());
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   64</span>     }
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   65</span>     <span style="COLOR: blue">string</span> pluralize(<span style="COLOR: blue">string</span> s)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   66</span>     {
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   67</span>         <span style="COLOR: blue">return</span> s.EndsWith(<span style="COLOR: #a31515">"s"</span>)
? s : s + <span style="COLOR: #a31515">"s"</span>;
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   68</span>     }
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   69</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   70</span>     T
getAttr&lt;T&gt;(<span style="COLOR: #2b91af">ICustomAttributeProvider</span> icap)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   71</span>     {
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   72</span>         <span style="COLOR: blue">var</span> a
= icap.GetCustomAttributes(<span style="COLOR: blue">typeof</span>(T), <span style="COLOR: blue">true</span>);
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   73</span>         <span style="COLOR: blue">return</span> a.Length
== 0 ? <span style="COLOR: blue">default</span>(T) : (T)a[0];
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   74</span>     }
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   75</span> }
</p>
        </div>
        <img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=ae23e7f3-a43e-4bc5-90cc-12b2b74dff99" />
      </body>
      <title>I underestimated the power of query comprehensions</title>
      <guid isPermaLink="false">http://www.atrevido.net/blog/PermaLink,guid,ae23e7f3-a43e-4bc5-90cc-12b2b74dff99.aspx</guid>
      <link>http://www.atrevido.net/blog/2008/06/26/I+Underestimated+The+Power+Of+Query+Comprehensions.aspx</link>
      <pubDate>Thu, 26 Jun 2008 06:15:10 GMT</pubDate>
      <description>&lt;p&gt;
In my &lt;a href="http://www.atrevido.net/blog/2008/06/26/LINQ+To+The+CRUD+CreateTable+Generator+In+F.aspx"&gt;last
post&lt;/a&gt;, I said I'd write the sample in C# to compare to F#. Well, I grossly underestimated
the power of query comprehensions. The C# version is almost the same length (formatting
differences, mainly). I'm surprised and impressed. (Or maybe I'm writing F# like I'd
write C#.) Edit: I think maybe sequence expressions could cut it down a bit...
&lt;/p&gt;
&lt;p&gt;
...But... C# still can't do discriminated unions efficiently or effectively ;). 
&lt;/p&gt;
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="FONT-SIZE: 11pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: Consolas"&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//
crudcreatecompare.cs: Generates LINQ CRUD table fields using the horribly named DatabaseBase
code&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//
Tables look like: [Table(Name="dbo.Accounts")]&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//
Columns look like this:&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&amp;nbsp;
[Column(Storage="_AccountName", DbType="VarChar(128) NOT NULL", CanBeNull=false, IsPrimaryKey=true)]&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&amp;nbsp;
[DataMember(Order=1)] // Exists if serialization is turned on; used to order key parameters&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//
Emits:&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&amp;nbsp;
public static readonly TableHelper&amp;lt;Account, String&amp;gt; Accounts =&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp; CreateTable(dc =&amp;gt; dc.Accounts, a =&amp;gt; a.AccountName);&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Data.Linq.Mapping;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.IO;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Linq;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Reflection;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt; System.Runtime.Serialization;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;class&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;Program&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;{
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;static&lt;/span&gt; &lt;span style="COLOR: blue"&gt;void&lt;/span&gt; Main()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;Program&lt;/span&gt;().generate(
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: #a31515"&gt;"C:\\yourlinq.dll"&lt;/span&gt;));
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; generate(&lt;span style="COLOR: blue"&gt;string&lt;/span&gt; asmpath)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;var&lt;/span&gt; asm
= &lt;span style="COLOR: #2b91af"&gt;Assembly&lt;/span&gt;.LoadFrom(asmpath);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;var&lt;/span&gt; lines
= &lt;span style="COLOR: blue"&gt;from&lt;/span&gt; t &lt;span style="COLOR: blue"&gt;in&lt;/span&gt; asm.GetExportedTypes()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;let&lt;/span&gt; ta
= getAttr&amp;lt;&lt;span style="COLOR: #2b91af"&gt;TableAttribute&lt;/span&gt;&amp;gt;(t)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;where&lt;/span&gt; ta
!= &lt;span style="COLOR: blue"&gt;null&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;let&lt;/span&gt; name
= pluralize(ta.Name.Replace(&lt;span style="COLOR: #a31515"&gt;"dbo."&lt;/span&gt;, &lt;span style="COLOR: #a31515"&gt;""&lt;/span&gt;))
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;orderby&lt;/span&gt; name
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;select&lt;/span&gt; genTable(t,
name);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; joinStrings(&lt;span style="COLOR: #a31515"&gt;""&lt;/span&gt;,
lines);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; genTable(&lt;span style="COLOR: #2b91af"&gt;Type&lt;/span&gt; t, &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; tableName)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;var&lt;/span&gt; keyProps
=
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;from&lt;/span&gt; p &lt;span style="COLOR: blue"&gt;in&lt;/span&gt; t.GetProperties()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;let&lt;/span&gt; c = getAttr&amp;lt;&lt;span style="COLOR: #2b91af"&gt;ColumnAttribute&lt;/span&gt;&amp;gt;(p)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;where&lt;/span&gt; c != &lt;span style="COLOR: blue"&gt;null&lt;/span&gt; &amp;amp;&amp;amp;
c.IsPrimaryKey
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;let&lt;/span&gt; dm = getAttr&amp;lt;&lt;span style="COLOR: #2b91af"&gt;DataMemberAttribute&lt;/span&gt;&amp;gt;(p)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;orderby&lt;/span&gt; dm == &lt;span style="COLOR: blue"&gt;null&lt;/span&gt; ?
0 : dm.Order
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;select&lt;/span&gt; p;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;var&lt;/span&gt; tw
= &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;StringWriter&lt;/span&gt;();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
tw.WriteLine(&lt;span style="COLOR: #a31515"&gt;"public static readonly TableHelper&amp;lt;{0},
{1}&amp;gt; {2} ="&lt;/span&gt;,
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; t.Name,
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; joinStrings(&lt;span style="COLOR: #a31515"&gt;", "&lt;/span&gt;, keyProps.Select(p
=&amp;gt; p.PropertyType.Name)),
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; tableName);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
tw.WriteLine(&lt;span style="COLOR: #a31515"&gt;"\tCreateTable(dc =&amp;gt; dc.{0}, {1});"&lt;/span&gt;,
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; tableName,
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; joinStrings(&lt;span style="COLOR: #a31515"&gt;", "&lt;/span&gt;, keyProps.Select(p
=&amp;gt; &lt;span style="COLOR: #a31515"&gt;"a =&amp;gt; a."&lt;/span&gt; + p.Name)));
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
tw.WriteLine();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; tw.ToString();
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;60&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;61&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; joinStrings(&lt;span style="COLOR: blue"&gt;string&lt;/span&gt; sep, &lt;span style="COLOR: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="COLOR: blue"&gt;string&lt;/span&gt;&amp;gt;
items)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;62&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;63&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt;.Join(sep,
items.ToArray());
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;64&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;65&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; pluralize(&lt;span style="COLOR: blue"&gt;string&lt;/span&gt; s)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;66&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;67&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; s.EndsWith(&lt;span style="COLOR: #a31515"&gt;"s"&lt;/span&gt;)
? s : s + &lt;span style="COLOR: #a31515"&gt;"s"&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;68&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;69&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;70&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T
getAttr&amp;lt;T&amp;gt;(&lt;span style="COLOR: #2b91af"&gt;ICustomAttributeProvider&lt;/span&gt; icap)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;71&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;72&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;var&lt;/span&gt; a
= icap.GetCustomAttributes(&lt;span style="COLOR: blue"&gt;typeof&lt;/span&gt;(T), &lt;span style="COLOR: blue"&gt;true&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;73&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; a.Length
== 0 ? &lt;span style="COLOR: blue"&gt;default&lt;/span&gt;(T) : (T)a[0];
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;74&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;75&lt;/span&gt;&amp;nbsp;}
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=ae23e7f3-a43e-4bc5-90cc-12b2b74dff99" /&gt;</description>
      <comments>http://www.atrevido.net/blog/CommentView,guid,ae23e7f3-a43e-4bc5-90cc-12b2b74dff99.aspx</comments>
      <category>Code</category>
      <category>F#</category>
    </item>
    <item>
      <trackback:ping>http://www.atrevido.net/blog/Trackback.aspx?guid=d6d66155-c288-4984-b4ba-4e58285daf7f</trackback:ping>
      <pingback:server>http://www.atrevido.net/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.atrevido.net/blog/PermaLink,guid,d6d66155-c288-4984-b4ba-4e58285daf7f.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.atrevido.net/blog/CommentView,guid,d6d66155-c288-4984-b4ba-4e58285daf7f.aspx</wfw:comment>
      <wfw:commentRss>http://www.atrevido.net/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=d6d66155-c288-4984-b4ba-4e58285daf7f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
With the <a href="http://www.atrevido.net/blog/2008/06/26/LINQ+To+The+CRUD+RTM.aspx">DatabaseBase</a> and
TableHelper classes, you still have to generate a CreateTable field per table. Why
do it by hand? I wrote an F# script to generate the statements. I must say, I'm
loving F# more than I had hoped. The more I learn, the better it gets. I've noticed
(even in C#) that using a functional style generally means less errors. This script
worked without bugs the first time (i.e., as soon as it compiled), which is pretty
cool (granted, it's not big, but I'm sure if I had tons of for loops, I woulda messed
up somewhere). Maybe this weekend I'll try writing it in C# just to compare (pretty
sure it'll be more than 59 lines!). And I'll preempt comments about readability:
Yes, it may be difficult to read if you don't know F#, but more on that later...
</p>
        <p>
I'd love feedback as to making it more "functional"; years of imperative programming
don't die quickly. Also, I'm not very happy with the definition of chooseAttr, but
I can't seem to get it to infer the type I want otherwise.
</p>
        <p>
Anyways, here's the code. You'll need to specify the references when compiling:
-r "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.Linq.dll"
-r "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\System.Runtime.Serialization.dll" 
</p>
        <p>
          <hr />
        </p>
        <p>
        </p>
        <div style="FONT-SIZE: 11pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: Consolas">
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    1</span> <span style="COLOR: green">//
crudcreatetable.fsx: Generates LINQ CRUD table fields using the horribly named DatabaseBase
code</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    2</span> <span style="COLOR: green">//</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    3</span> <span style="COLOR: green">//
Tables look like: [Table(Name="dbo.Accounts")]</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    4</span> <span style="COLOR: green">//
Columns look like this:</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    5</span> <span style="COLOR: green">// 
[Column(Storage="_AccountName", DbType="VarChar(128) NOT NULL", CanBeNull=false, IsPrimaryKey=true)]</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    6</span> <span style="COLOR: green">// 
[DataMember(Order=1)] // Exists if serialization is turned on; used to order key parameters</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    7</span> <span style="COLOR: green">//
Emits:</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    8</span> <span style="COLOR: green">// 
public static readonly TableHelper&lt;Account, String&gt; Accounts =</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">    9</span> <span style="COLOR: green">//   
  CreateTable(dc =&gt; dc.Accounts, a =&gt; a.AccountName);</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   10</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   11</span> #light
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   12</span> <span style="COLOR: blue">open</span> System
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   13</span> <span style="COLOR: blue">open</span> System.Reflection
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   14</span> <span style="COLOR: blue">open</span> System.Data.Linq.Mapping
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   15</span> <span style="COLOR: blue">open</span> System.Runtime.Serialization
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   16</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   17</span> <span style="COLOR: blue">let</span> getAttr&lt;'target,
'a <span style="COLOR: blue">when</span> 'a :&gt; ICustomAttributeProvider&gt; (ty
: 'a) = 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   18</span>     <span style="COLOR: blue">match</span> List.of_array
(ty.GetCustomAttributes(typeof&lt;'target&gt;, <span style="COLOR: blue">true</span>)) <span style="COLOR: blue">with</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   19</span>        
| a::_ <span style="COLOR: blue">-&gt;</span> Some (a :?&gt; 'target)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   20</span>        
| [] <span style="COLOR: blue">-&gt;</span> None
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   21</span> <span style="COLOR: blue">let</span> chooseAttr&lt;'target,
'a <span style="COLOR: blue">when</span> 'a :&gt; ICustomAttributeProvider&gt; (ty
: 'a) = 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   22</span>     <span style="COLOR: blue">match</span> getAttr&lt;'target,_&gt;
ty <span style="COLOR: blue">with</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   23</span>        
| Some(a) <span style="COLOR: blue">-&gt;</span> Some(ty,a)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   24</span>        
| None <span style="COLOR: blue">-&gt;</span> None
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   25</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   26</span> <span style="COLOR: blue">let</span> joinStrings
(sep:string) items = items |&gt; Seq.fold1 (<span style="COLOR: blue">fun</span> acc
x <span style="COLOR: blue">-&gt;</span> acc + sep + x) 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   27</span> <span style="COLOR: blue">let</span> pluralize
(name:string) = <span style="COLOR: blue">if</span> name.EndsWith(<span style="COLOR: #a31515">"s"</span>) <span style="COLOR: blue">then</span> name <span style="COLOR: blue">else</span> name
+ <span style="COLOR: #a31515">"s"</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   28</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   29</span> <span style="COLOR: blue">let</span> generate(asmpath:string)
=
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   30</span>     <span style="COLOR: blue">let</span> genTable
(t:Type, tableName) =
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   31</span>         <span style="COLOR: blue">let</span> keyProps
= 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   32</span>        
    t.GetProperties() 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   33</span>        
    |&gt; Seq.choose (chooseAttr&lt;ColumnAttribute,_&gt;)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   34</span>        
    |&gt; Seq.filter(<span style="COLOR: blue">fun</span> (p,c) <span style="COLOR: blue">-&gt;</span> c.IsPrimaryKey)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   35</span>        
    |&gt; Seq.map(<span style="COLOR: blue">fun</span> (p,_) <span style="COLOR: blue">-&gt;</span> p,
getAttr&lt;DataMemberAttribute, _&gt; p)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   36</span>        
    |&gt; Seq.orderBy(<span style="COLOR: blue">function</span> | _,Some(dm) <span style="COLOR: blue">-&gt;</span> dm.Order
| _ <span style="COLOR: blue">-&gt;</span> 0)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   37</span>        
    |&gt; Seq.map (<span style="COLOR: blue">fun</span> (p,_) <span style="COLOR: blue">-&gt;</span> p)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   38</span>         <span style="COLOR: blue">let</span> tw
= <span style="COLOR: blue">new</span> IO.StringWriter()
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   39</span>         <span style="COLOR: blue">let</span> pn
fmt = Printf.twprintfn tw fmt
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   40</span>        
pn <span style="COLOR: #a31515">"public static readonly TableHelper&lt;%s, %s&gt;
%s ="</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   41</span>        
    t.Name 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   42</span>        
    (joinStrings <span style="COLOR: #a31515">", "</span> (keyProps
|&gt; Seq.map (<span style="COLOR: blue">fun</span> p <span style="COLOR: blue">-&gt;</span> p.PropertyType.Name)))
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   43</span>        
    tableName
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   44</span>        
pn <span style="COLOR: #a31515">"\tCreateTable(dc =&gt; dc.%s, %s);"</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   45</span>        
    tableName
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   46</span>        
    (joinStrings <span style="COLOR: #a31515">", "</span> (keyProps
|&gt; Seq.map (<span style="COLOR: blue">fun</span> p <span style="COLOR: blue">-&gt;</span><span style="COLOR: #a31515">"a
=&gt; a."</span> + p.Name)))
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   47</span>        
pn <span style="COLOR: #a31515">""</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   48</span>        
tw.ToString()
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   49</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   50</span>     <span style="COLOR: blue">let</span> asm
= Assembly.LoadFrom asmpath <span style="COLOR: green">// Don't use ReflectionOnly
'cause it won't resolve dependencies</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   51</span>     asm.GetExportedTypes
() 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   52</span>        
|&gt; Seq.choose (chooseAttr&lt;TableAttribute,_&gt;)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   53</span>        
|&gt; Seq.map (<span style="COLOR: blue">fun</span> (t,ta) <span style="COLOR: blue">-&gt;</span> t,
ta.Name.Replace(<span style="COLOR: #a31515">"dbo."</span>, <span style="COLOR: #a31515">""</span>)
|&gt; pluralize)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   54</span>        
|&gt; Seq.orderBy (<span style="COLOR: blue">fun</span> (t,_) <span style="COLOR: blue">-&gt;</span> t.Name)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   55</span>        
|&gt; Seq.map genTable
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   56</span>        
|&gt; Seq.fold1 (+)
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   57</span> 
</p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   58</span> generate <span style="COLOR: #a31515">"C:\\yourlinq.dll"</span></p>
          <p style="MARGIN: 0px">
            <span style="COLOR: #2b91af">   59</span>     |&gt;
Console.WriteLine
</p>
        </div>
        <img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=d6d66155-c288-4984-b4ba-4e58285daf7f" />
      </body>
      <title>LINQ to the CRUD CreateTable generator in F#</title>
      <guid isPermaLink="false">http://www.atrevido.net/blog/PermaLink,guid,d6d66155-c288-4984-b4ba-4e58285daf7f.aspx</guid>
      <link>http://www.atrevido.net/blog/2008/06/26/LINQ+To+The+CRUD+CreateTable+Generator+In+F.aspx</link>
      <pubDate>Thu, 26 Jun 2008 05:13:44 GMT</pubDate>
      <description>&lt;p&gt;
With the &lt;a href="http://www.atrevido.net/blog/2008/06/26/LINQ+To+The+CRUD+RTM.aspx"&gt;DatabaseBase&lt;/a&gt; and
TableHelper classes, you still have to generate a CreateTable field per table. Why
do it by hand? I wrote an F#&amp;nbsp;script to generate the statements. I must say, I'm
loving F# more than I had hoped. The more I learn, the better it gets. I've noticed
(even in C#) that using a functional style generally means less errors. This script
worked without bugs the first time (i.e., as soon as it compiled), which is pretty
cool (granted, it's not big, but I'm sure if I had tons of for loops, I woulda messed
up somewhere). Maybe this weekend I'll try writing it in C# just to compare (pretty
sure it'll be more than 59 lines!). And I'll preempt comments&amp;nbsp;about readability:
Yes, it may be difficult to read if you don't know F#, but more on that later...
&lt;/p&gt;
&lt;p&gt;
I'd love feedback as to making it more "functional"; years of imperative programming
don't die quickly. Also, I'm not very happy with the definition of chooseAttr, but
I can't seem to get it to infer the type I want otherwise.
&lt;/p&gt;
&lt;p&gt;
Anyways, here's the code.&amp;nbsp;You'll need to specify the references when compiling:
-r "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.Linq.dll"
-r "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\System.Runtime.Serialization.dll" 
&lt;/p&gt;
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="FONT-SIZE: 11pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: Consolas"&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//
crudcreatetable.fsx: Generates LINQ CRUD table fields using the horribly named DatabaseBase
code&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//
Tables look like: [Table(Name="dbo.Accounts")]&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//
Columns look like this:&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&amp;nbsp;
[Column(Storage="_AccountName", DbType="VarChar(128) NOT NULL", CanBeNull=false, IsPrimaryKey=true)]&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&amp;nbsp;
[DataMember(Order=1)] // Exists if serialization is turned on; used to order key parameters&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//
Emits:&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&amp;nbsp;
public static readonly TableHelper&amp;lt;Account, String&amp;gt; Accounts =&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: green"&gt;//&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp; CreateTable(dc =&amp;gt; dc.Accounts, a =&amp;gt; a.AccountName);&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;#light
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;open&lt;/span&gt; System
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;open&lt;/span&gt; System.Reflection
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;open&lt;/span&gt; System.Data.Linq.Mapping
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;open&lt;/span&gt; System.Runtime.Serialization
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;let&lt;/span&gt; getAttr&amp;lt;'target,
'a &lt;span style="COLOR: blue"&gt;when&lt;/span&gt; 'a :&amp;gt; ICustomAttributeProvider&amp;gt; (ty
: 'a) = 
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;match&lt;/span&gt; List.of_array
(ty.GetCustomAttributes(typeof&amp;lt;'target&amp;gt;, &lt;span style="COLOR: blue"&gt;true&lt;/span&gt;)) &lt;span style="COLOR: blue"&gt;with&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
| a::_ &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; Some (a :?&amp;gt; 'target)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
| [] &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; None
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;let&lt;/span&gt; chooseAttr&amp;lt;'target,
'a &lt;span style="COLOR: blue"&gt;when&lt;/span&gt; 'a :&amp;gt; ICustomAttributeProvider&amp;gt; (ty
: 'a) = 
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;match&lt;/span&gt; getAttr&amp;lt;'target,_&amp;gt;
ty &lt;span style="COLOR: blue"&gt;with&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
| Some(a) &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; Some(ty,a)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
| None &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; None
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;let&lt;/span&gt; joinStrings
(sep:string) items = items |&amp;gt; Seq.fold1 (&lt;span style="COLOR: blue"&gt;fun&lt;/span&gt; acc
x &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; acc + sep + x) 
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;let&lt;/span&gt; pluralize
(name:string) = &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; name.EndsWith(&lt;span style="COLOR: #a31515"&gt;"s"&lt;/span&gt;) &lt;span style="COLOR: blue"&gt;then&lt;/span&gt; name &lt;span style="COLOR: blue"&gt;else&lt;/span&gt; name
+ &lt;span style="COLOR: #a31515"&gt;"s"&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR: blue"&gt;let&lt;/span&gt; generate(asmpath:string)
=
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;let&lt;/span&gt; genTable
(t:Type, tableName) =
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;let&lt;/span&gt; keyProps
= 
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; t.GetProperties() 
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;gt; Seq.choose (chooseAttr&amp;lt;ColumnAttribute,_&amp;gt;)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;gt; Seq.filter(&lt;span style="COLOR: blue"&gt;fun&lt;/span&gt; (p,c) &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; c.IsPrimaryKey)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;gt; Seq.map(&lt;span style="COLOR: blue"&gt;fun&lt;/span&gt; (p,_) &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; p,
getAttr&amp;lt;DataMemberAttribute, _&amp;gt; p)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;gt; Seq.orderBy(&lt;span style="COLOR: blue"&gt;function&lt;/span&gt; | _,Some(dm) &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; dm.Order
| _ &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; 0)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;gt; Seq.map (&lt;span style="COLOR: blue"&gt;fun&lt;/span&gt; (p,_) &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; p)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;let&lt;/span&gt; tw
= &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; IO.StringWriter()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;let&lt;/span&gt; pn
fmt = Printf.twprintfn tw fmt
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
pn &lt;span style="COLOR: #a31515"&gt;"public static readonly TableHelper&amp;lt;%s, %s&amp;gt;
%s ="&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; t.Name 
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; (joinStrings &lt;span style="COLOR: #a31515"&gt;", "&lt;/span&gt; (keyProps
|&amp;gt; Seq.map (&lt;span style="COLOR: blue"&gt;fun&lt;/span&gt; p &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; p.PropertyType.Name)))
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; tableName
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
pn &lt;span style="COLOR: #a31515"&gt;"\tCreateTable(dc =&amp;gt; dc.%s, %s);"&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; tableName
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp; (joinStrings &lt;span style="COLOR: #a31515"&gt;", "&lt;/span&gt; (keyProps
|&amp;gt; Seq.map (&lt;span style="COLOR: blue"&gt;fun&lt;/span&gt; p &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"a
=&amp;gt; a."&lt;/span&gt; + p.Name)))
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
pn &lt;span style="COLOR: #a31515"&gt;""&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
tw.ToString()
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;let&lt;/span&gt; asm
= Assembly.LoadFrom asmpath &lt;span style="COLOR: green"&gt;// Don't use ReflectionOnly
'cause it won't resolve dependencies&lt;/span&gt;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; asm.GetExportedTypes
() 
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
|&amp;gt; Seq.choose (chooseAttr&amp;lt;TableAttribute,_&amp;gt;)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
|&amp;gt; Seq.map (&lt;span style="COLOR: blue"&gt;fun&lt;/span&gt; (t,ta) &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; t,
ta.Name.Replace(&lt;span style="COLOR: #a31515"&gt;"dbo."&lt;/span&gt;, &lt;span style="COLOR: #a31515"&gt;""&lt;/span&gt;)
|&amp;gt; pluralize)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
|&amp;gt; Seq.orderBy (&lt;span style="COLOR: blue"&gt;fun&lt;/span&gt; (t,_) &lt;span style="COLOR: blue"&gt;-&amp;gt;&lt;/span&gt; t.Name)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
|&amp;gt; Seq.map genTable
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;
|&amp;gt; Seq.fold1 (+)
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;generate &lt;span style="COLOR: #a31515"&gt;"C:\\yourlinq.dll"&lt;/span&gt; 
&lt;/p&gt;
&lt;p style="MARGIN: 0px"&gt;
&lt;span style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;gt;
Console.WriteLine
&lt;/p&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=d6d66155-c288-4984-b4ba-4e58285daf7f" /&gt;</description>
      <comments>http://www.atrevido.net/blog/CommentView,guid,d6d66155-c288-4984-b4ba-4e58285daf7f.aspx</comments>
      <category>F#</category>
    </item>
    <item>
      <trackback:ping>http://www.atrevido.net/blog/Trackback.aspx?guid=7fb8423f-ac62-49ae-a01a-e82517c602b0</trackback:ping>
      <pingback:server>http://www.atrevido.net/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.atrevido.net/blog/PermaLink,guid,7fb8423f-ac62-49ae-a01a-e82517c602b0.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.atrevido.net/blog/CommentView,guid,7fb8423f-ac62-49ae-a01a-e82517c602b0.aspx</wfw:comment>
      <wfw:commentRss>http://www.atrevido.net/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=7fb8423f-ac62-49ae-a01a-e82517c602b0</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
[Reposting because it appears to have been deleted somehow.]
</p>
        <p>
A bit ago, I posted some info on doing CRUD operations using LINQ: <a href="http://www.atrevido.net/blog/2007/08/26/A+LINQ+To+The+CRUD.aspx">http://www.atrevido.net/blog/2007/08/26/A+LINQ+To+The+CRUD.aspx</a></p>
        <p>
This is a lightweight way (no codegen at all, only 2 lines of code per table) to get
some CRUD stuff with LINQ. It's not the most efficient or fantastic way of doing things,
but it works fine in the several projects we've used it so far. And we get to use
C# 3's expression trees, which is a fantastic and under-exploited feature. At
any rate, it does show that doing disconnected work with LINQ is trivial. 
</p>
        <p>
The code I posted was for Beta 2 and no longer works. I've since added a few new features,
but the basic idea remains the same as before. I'm just posting the new code as I've
gotten a few emails and one comment about the old code no longer working. 
</p>
        <p>
          <a href="http://www.atrevido.net/blog/content/binary/DatabaseBase.cs.txt">DatabaseBase.cs
(10.47 KB)</a>
        </p>
        <p>
While working on it in a real project, I started using our Tuple struct, so you'll
need that too:<br /><a href="http://www.atrevido.net/blog/content/binary/Tuple.cs.txt">Tuple.cs (2.8 KB)</a></p>
        <p>
As Scott Peterson pointed out, this class doesn't implement IEquatable&lt;T&gt;. Just
add it and call the == operator.
</p>
        <p>
As always I welcome any criticism. 
</p>
        <img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=7fb8423f-ac62-49ae-a01a-e82517c602b0" />
      </body>
      <title>LINQ to the CRUD RTM</title>
      <guid isPermaLink="false">http://www.atrevido.net/blog/PermaLink,guid,7fb8423f-ac62-49ae-a01a-e82517c602b0.aspx</guid>
      <link>http://www.atrevido.net/blog/2008/06/26/LINQ+To+The+CRUD+RTM.aspx</link>
      <pubDate>Thu, 26 Jun 2008 04:56:24 GMT</pubDate>
      <description>&lt;p&gt;
[Reposting because it appears to have been deleted somehow.]
&lt;/p&gt;
&lt;p&gt;
A bit ago, I posted some info on doing CRUD operations using LINQ: &lt;a href="http://www.atrevido.net/blog/2007/08/26/A+LINQ+To+The+CRUD.aspx"&gt;http://www.atrevido.net/blog/2007/08/26/A+LINQ+To+The+CRUD.aspx&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
This is a lightweight way (no codegen at all, only 2 lines of code per table) to get
some CRUD stuff with LINQ. It's not the most efficient or fantastic way of doing things,
but it works fine in the several projects we've used it so far. And we get to use
C# 3's expression trees, which is&amp;nbsp;a fantastic and under-exploited feature.&amp;nbsp;At
any rate, it does show that doing disconnected work with LINQ is trivial. 
&lt;/p&gt;
&lt;p&gt;
The code I posted was for Beta 2 and no longer works. I've since added a few new features,
but the basic idea remains the same as before. I'm just posting the new code as I've
gotten a few emails and one comment about the old code no longer working. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.atrevido.net/blog/content/binary/DatabaseBase.cs.txt"&gt;DatabaseBase.cs
(10.47 KB)&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
While working on it in a real project, I started using our Tuple struct, so you'll
need that too:&lt;br&gt;
&lt;a href="http://www.atrevido.net/blog/content/binary/Tuple.cs.txt"&gt;Tuple.cs (2.8 KB)&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
As Scott Peterson pointed out, this class doesn't implement IEquatable&amp;lt;T&amp;gt;. Just
add it and call the == operator.
&lt;/p&gt;
&lt;p&gt;
As always I welcome any criticism. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=7fb8423f-ac62-49ae-a01a-e82517c602b0" /&gt;</description>
      <comments>http://www.atrevido.net/blog/CommentView,guid,7fb8423f-ac62-49ae-a01a-e82517c602b0.aspx</comments>
      <category>Misc. Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.atrevido.net/blog/Trackback.aspx?guid=1613baf7-ed7e-4ecc-bd10-4106ea3c88bc</trackback:ping>
      <pingback:server>http://www.atrevido.net/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.atrevido.net/blog/PermaLink,guid,1613baf7-ed7e-4ecc-bd10-4106ea3c88bc.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.atrevido.net/blog/CommentView,guid,1613baf7-ed7e-4ecc-bd10-4106ea3c88bc.aspx</wfw:comment>
      <wfw:commentRss>http://www.atrevido.net/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=1613baf7-ed7e-4ecc-bd10-4106ea3c88bc</wfw:commentRss>
      <slash:comments>8</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
No support for anonymous methods/lambda statements. I first realised this when
someone commented on one of my <a href="http://www.atrevido.net/blog/2007/08/26/A+LINQ+To+The+CRUD.aspx">functional
C#</a> postings, asking "how can I write this in VB"? Turns out VB has no support
for anonymous methods. <a href="http://www.paulstovell.com/blog/vbnet-wheres-actiont-support">Ouch.</a></p>
        <p>
This lack of capability rules out a so much functionality, I honestly cannot imagine
writing anything significant today using VB.NET. But with LINQ and F# making such
a big splashes, I have high hopes for the future of functional programming on the
.NET languages, and I'm sure VB.NET will get itself fixed up. 
</p>
        <p>
Really, dropping anonymous methods in favour of stuff like XML literals? Maybe that's
why it's listed as <a href="http://msmvps.com/blogs/bill/archive/2008/03/23/first-time-or-casual-programming.aspx">first
time or casual programming</a> ;). (No, I jest. Scheme is far better for first
time programming.)
</p>
        <img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=1613baf7-ed7e-4ecc-bd10-4106ea3c88bc" />
      </body>
      <title>The reason VB.NET is truly a second class citizen</title>
      <guid isPermaLink="false">http://www.atrevido.net/blog/PermaLink,guid,1613baf7-ed7e-4ecc-bd10-4106ea3c88bc.aspx</guid>
      <link>http://www.atrevido.net/blog/2008/03/31/The+Reason+VBNET+Is+Truly+A+Second+Class+Citizen.aspx</link>
      <pubDate>Mon, 31 Mar 2008 21:55:56 GMT</pubDate>
      <description>&lt;p&gt;
No support for anonymous methods/lambda statements.&amp;nbsp;I first realised this when
someone commented on one of my &lt;a href="http://www.atrevido.net/blog/2007/08/26/A+LINQ+To+The+CRUD.aspx"&gt;functional
C#&lt;/a&gt; postings, asking "how can I write this in VB"? Turns out VB has no support
for anonymous methods. &lt;a href="http://www.paulstovell.com/blog/vbnet-wheres-actiont-support"&gt;Ouch.&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
This lack of capability rules out a so much functionality, I honestly cannot imagine
writing anything significant today using VB.NET. But with LINQ and F# making such
a big splashes, I have high hopes for the future of functional programming on the
.NET languages, and I'm sure VB.NET will get itself fixed up. 
&lt;/p&gt;
&lt;p&gt;
Really, dropping anonymous methods in favour of stuff like XML literals? Maybe that's
why it's listed as &lt;a href="http://msmvps.com/blogs/bill/archive/2008/03/23/first-time-or-casual-programming.aspx"&gt;first
time or casual programming&lt;/a&gt;&amp;nbsp;;). (No, I jest. Scheme is far better for first
time programming.)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=1613baf7-ed7e-4ecc-bd10-4106ea3c88bc" /&gt;</description>
      <comments>http://www.atrevido.net/blog/CommentView,guid,1613baf7-ed7e-4ecc-bd10-4106ea3c88bc.aspx</comments>
      <category>Code</category>
    </item>
    <item>
      <trackback:ping>http://www.atrevido.net/blog/Trackback.aspx?guid=ddab93db-ef59-4084-ba60-aa7dba01412e</trackback:ping>
      <pingback:server>http://www.atrevido.net/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.atrevido.net/blog/PermaLink,guid,ddab93db-ef59-4084-ba60-aa7dba01412e.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.atrevido.net/blog/CommentView,guid,ddab93db-ef59-4084-ba60-aa7dba01412e.aspx</wfw:comment>
      <wfw:commentRss>http://www.atrevido.net/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=ddab93db-ef59-4084-ba60-aa7dba01412e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Usually I use WCF just by referencing the contracts directly and using my own <a href="http://www.atrevido.net/blog/2007/08/13/Practical+Functional+C+Part+II.aspx">generic
helper methods</a>. Unfortunately, I had to make use of the built-in async patterns
that the codegen can provide. Hence, I ended up using the "Add Service Reference"
dialog, which notices (unlike svcutil on the command line) that since I'm requesting
async, it'll need to generate my interfaces even though they're already referenced.
Maybe in .NET 4 we'll have a new async pattern that'll leverage Expression Trees to
rid us of having to use the rather ugly FooAsync/BeingFoo patterns. 
</p>
        <p>
Things were working just fine until I added a reference to a new service. Adding the
service reference didn't work; it failed silently. It added all the schema files to
the project, but the Reference.cs file was empty. If I told it to NOT used referenced
assemblies, then it generated everything just fine.
</p>
        <p>
After switching to the command line and using svcutil, I got these errors:<br /><font face="Courier New">Error: Cannot import wsdl:portType<br />
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter<br />
Error: Referenced type 'MyApp.Management.CoolFunction.CoolThingRule, MyApp.Management.Contracts,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' with data contract name 'CoolThingRule'
in namespace 'http://schemas.MyApp.com/management/v2/00' cannot be used since it does
not match imported DataContract. Need to exclude this type from referenced types.XPath
to Error Source: //wsdl:definitions[@targetNamespace='http://schemas.MyApp.com/management/v2/00']/wsdl:portType[@name='ICoolThingManagement']</font></p>
        <p>
I regenerated without the referenced code and figured out that the problem was that
one type referenced an enum which had some values without the [EnumMember] attribute
(although it had a DataContractAttribute on the enum itself). Because of this, WCF
wanted to represent the enum with a string and thus was incompatible. Adding the EnumMemberAttribute
to all the values sorted out this issue.
</p>
        <img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=ddab93db-ef59-4084-ba60-aa7dba01412e" />
      </body>
      <title>Empty WCF services references - no code generated</title>
      <guid isPermaLink="false">http://www.atrevido.net/blog/PermaLink,guid,ddab93db-ef59-4084-ba60-aa7dba01412e.aspx</guid>
      <link>http://www.atrevido.net/blog/2008/03/31/Empty+WCF+Services+References+No+Code+Generated.aspx</link>
      <pubDate>Mon, 31 Mar 2008 09:06:51 GMT</pubDate>
      <description>&lt;p&gt;
Usually I use WCF just by referencing the contracts directly and using my own &lt;a href="http://www.atrevido.net/blog/2007/08/13/Practical+Functional+C+Part+II.aspx"&gt;generic
helper methods&lt;/a&gt;. Unfortunately, I had to make use of the built-in async patterns
that the codegen can provide. Hence, I ended up using the "Add Service Reference"
dialog, which notices (unlike svcutil on the command line) that since I'm requesting
async, it'll need to generate my interfaces even though they're already referenced.
Maybe in .NET 4 we'll have a new async pattern that'll leverage Expression Trees to
rid us of having to use the rather ugly FooAsync/BeingFoo patterns. 
&lt;/p&gt;
&lt;p&gt;
Things were working just fine until I added a reference to a new service. Adding the
service reference didn't&amp;nbsp;work; it failed silently. It added all the schema files&amp;nbsp;to
the project, but the Reference.cs file was empty.&amp;nbsp;If I told it to NOT used&amp;nbsp;referenced
assemblies, then it generated everything just fine.
&lt;/p&gt;
&lt;p&gt;
After switching to the command line and using svcutil, I got these errors:&lt;br&gt;
&lt;font face="Courier New"&gt;Error: Cannot import wsdl:portType&lt;br&gt;
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter&lt;br&gt;
Error: Referenced type 'MyApp.Management.CoolFunction.CoolThingRule, MyApp.Management.Contracts,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' with data contract name 'CoolThingRule'
in namespace 'http://schemas.MyApp.com/management/v2/00' cannot be used since it does
not match imported DataContract. Need to exclude this type from referenced types.XPath
to Error Source: //wsdl:definitions[@targetNamespace='http://schemas.MyApp.com/management/v2/00']/wsdl:portType[@name='ICoolThingManagement']&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
I regenerated without the referenced code and figured out that the problem was that
one type referenced an enum which had some values without the [EnumMember] attribute
(although it had a DataContractAttribute on the enum itself). Because of this, WCF
wanted to represent the enum with a string and thus was incompatible. Adding the EnumMemberAttribute
to all the values sorted out this issue.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=ddab93db-ef59-4084-ba60-aa7dba01412e" /&gt;</description>
      <comments>http://www.atrevido.net/blog/CommentView,guid,ddab93db-ef59-4084-ba60-aa7dba01412e.aspx</comments>
      <category>Code</category>
    </item>
    <item>
      <trackback:ping>http://www.atrevido.net/blog/Trackback.aspx?guid=ffa70c25-0c78-474b-8d60-10a693ffc407</trackback:ping>
      <pingback:server>http://www.atrevido.net/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.atrevido.net/blog/PermaLink,guid,ffa70c25-0c78-474b-8d60-10a693ffc407.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.atrevido.net/blog/CommentView,guid,ffa70c25-0c78-474b-8d60-10a693ffc407.aspx</wfw:comment>
      <wfw:commentRss>http://www.atrevido.net/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=ffa70c25-0c78-474b-8d60-10a693ffc407</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Silverlight 2 is pretty nice. Compared to dealing with the nightmare of HTML, CSS,
AJAX and whatever else, it's quite divine. Of particular interest is that Silverlight
2 has a mini Windows Communication Foundation stack that can do basic SOAP work (and
some "Web 2.0" type things too I think). While the SL WCF stack works pretty well
overall, it doesn't support SOAP faults.
</p>
        <p>
First off, SOAP faults usually cause the server to return an HTTP 500. For whatever
reasons, this isn't handled correctly between the browser and Silverlight, and results
in an UnexpectedHttpResponseCode. OK, so go into the Global.asax and in Application_EndRequest
change 500s to 200s. [Yes, this requires that you run WCF with AspNetCompatibility.]
</p>
        <p>
Some progress. Silverlight now gives a more useful exception:
</p>
        <p>
          <font face="Courier New">Error: System.Runtime.Serialization.SerializationException:
OperationFormatter encountered an invalid Message body. Expected to find node type
'Element' with name 'MyFunctionResponse' and namespace 'http://schemas.contoso.com/coolservice/v2/00'.
Found node type 'Element' with name 's:Fault' and namespace 'http://schemas.xmlsoap.org/soap/envelope/'</font>
        </p>
        <p>
Hmm, it's getting the fault, but can't seem to handle it. I tried adding typed faults
to my WCF contract, but the SL WCF stack doesn't have the FaultContractAttribute.
It appears as if SL cannot read faults at all.
</p>
        <p>
Enter HackFaults. That message provides two pieces of data from the SOAP message,
the element name, and the namespace. We can hijack these to pass our fault information,
then extract it from the exception message. H to the A to the C-K-Y.
</p>
        <p>
First off, we need to get access to our WCF fault. We can do this with an System.ServiceModel.Dispatcher.IErrorHandler.
I've attached the full code, but basically you add an attribute to your WCF service
to wire up the error handler. If you're doing WCF work, you probably want this
anyways for logging purposes and so on. I've attached the entire error handler code
to this article. The real meat of the error handler is this little function:
</p>
        <p>
          <font size="3">
            <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">public</span>
              <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> ProvideFault(Exception
error, MessageVersion version, <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ref</span> Message
fault)<br />
{<br />
    <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
HackFaults store the exception in the httpcontext</span><br />
    var context <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> System.Web.HttpContext.Current;<br />
    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (context
!<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>)
{ 
<br />
        <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
Only works in AspNetCompat mode</span><br />
        <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (!context.Request.Browser.Crawler
&amp;&amp; context.Request.Browser.EcmaScriptVersion.Major &gt; 0) {<br />
            <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
This should rule out non-browsers</span><br />
            context.Items.Add(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"HackFault"</span>,
error);<br />
        }<br />
    }<br />
}<br /></span>
          </font>
        </p>
        <p>
I'm not sure if there's a better way to differentiate between browsers and real SOAP
stacks. If there is let me know. Now, in our Global.asax, we want to pick this information
up and replace the actual SOAP fault with our own hackfault:
</p>
        <pre>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">protected</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">void</span> Application_EndRequest(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">object</span> sender,
EventArgs e) { <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
In all fairness, I was drinking eiswein at the time</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (Context.Items.Contains(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"HackFault"</span>))
{ Context.Response.ContentType <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"text/xml"</span>;
Context.Response.StatusCode <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> 200;
Context.Response.ClearContent(); var hackEx <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> Context.Items[<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"HackFault"</span>] <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">as</span> Exception;
var hackFaultXml <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">string</span>.Format( <span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"&lt;s:Envelope
xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt;&lt;s:Body&gt;&lt;{0} xmlns=\"{1}\"
/&gt;&lt;/s:Body&gt;&lt;/s:Envelope&gt;"</span>, hackEx.GetType().ToString(), Context.Server.HtmlEncode(hackEx.Message));
Context.Response.Output.Write(hackFaultXml); } } </span>
        </pre>
        <p>
Now we have a message that has the bits of data we care about in the right places
for the Silverlight exception to be ready for parsing. The SL-side parsing
code is vile but easy:
</p>
        <pre>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">public</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">static</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">string</span> ExtractHackFaultMessage(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">this</span> Exception
ex) { <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
HackFaults generate these Exceptions and messages:</span><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//Without
debug:</span><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//Could
not connect to server: System.Runtime.Serialization.SerializationException: [SFxInvalidMessageBody]</span><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//Arguments:FaultException,Something
silly</span><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//With
debug:</span><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//Could
not connect to server: System.Runtime.Serialization.SerializationException: 
<br /></span></span>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">OperationFormatter
encountered an invalid Message body. Expected to find node type 'Element' with 
<br />
name 'SomeOperationResponse' and namespace 'http://schemas.cool.com/yea/v2/00'. 
<br />
Found node type 'Element' with name 'FaultException' and namespace 'Something silly'</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (!(ex <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">is</span> System.Runtime.Serialization.SerializationException)) <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">return</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>;
var msg <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> ex.Message; <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">string</span> regexp; <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (msg.Contains(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"[SFxInvalidMessageBody]"</span>))
{ regexp <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">@"Arguments:(.*),(.*)"</span>;
} <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">else</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (msg.Contains(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"OperationFormatter
encountered an invalid Message body"</span>)) { regexp <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">@"Found
node type 'Element' with name '(.*)' and namespace '(.*)'"</span>; } <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">else</span> { <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
Nope, it's some thing else</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">return</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>;
} var match <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> System.Text.RegularExpressions.Regex.Match(msg,
regexp); <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (match.Groups.Count
!<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> 3) <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">return</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">null</span>; <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">//
Not expected</span> var exType <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> match.Groups[1].Value.Trim();
var exMsg <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> match.Groups[2].Value.Trim(); <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">if</span> (exType
== <span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"System.ServiceModel.FaultException"</span>) <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">return</span> exMsg; <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">else</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">return</span> exType+ <span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">":
"</span><span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">+</span> exMsg;
}</span>
        </pre>
        <p>
This little function will give me the fault information (and not mention FaultException
if that's what it is) or null if it can't extract it. When dealing with errors, I
can show an error like this: "Error: " + (ex.ExtractHackFaultMessage() ?? ex.ToString())
</p>
        <p>
This gives me at least rudimentary error reporting from the server back to Silverlight.
If this can be improved or fixed up, please tell me. (Typed fault exceptions would
be nice, but then SL can't codegen the contracts.) At any rate, it works as a cheap
hack until Silverlight Beta 2 (they gotta fix it by then, right? Right?).
</p>
        <a href="http://www.atrevido.net/blog/content/binary/HttpErrorHandler.cs.txt">HttpErrorHandler.cs.txt
(2.49 KB)</a>
        <img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=ffa70c25-0c78-474b-8d60-10a693ffc407" />
      </body>
      <title>Hacking SOAP Faults into Silverlight 2 Beta 1</title>
      <guid isPermaLink="false">http://www.atrevido.net/blog/PermaLink,guid,ffa70c25-0c78-474b-8d60-10a693ffc407.aspx</guid>
      <link>http://www.atrevido.net/blog/2008/03/27/Hacking+SOAP+Faults+Into+Silverlight+2+Beta+1.aspx</link>
      <pubDate>Thu, 27 Mar 2008 07:19:36 GMT</pubDate>
      <description>&lt;p&gt;
Silverlight 2 is pretty nice. Compared to dealing with the nightmare of HTML, CSS,
AJAX and whatever else, it's quite divine. Of particular interest is that Silverlight
2 has a mini Windows Communication Foundation stack that can do basic SOAP work (and
some "Web 2.0" type things too I think). While the SL WCF stack works pretty well
overall, it doesn't support SOAP faults.
&lt;/p&gt;
&lt;p&gt;
First off, SOAP faults usually cause the server to return an HTTP 500. For whatever
reasons, this isn't handled correctly between the browser and Silverlight, and results
in an UnexpectedHttpResponseCode. OK, so go into the Global.asax and in Application_EndRequest
change 500s to 200s. [Yes, this requires that you run WCF with AspNetCompatibility.]
&lt;/p&gt;
&lt;p&gt;
Some progress. Silverlight now gives a more useful exception:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;Error: System.Runtime.Serialization.SerializationException:
OperationFormatter encountered an invalid Message body. Expected to find node type
'Element' with name 'MyFunctionResponse' and namespace 'http://schemas.contoso.com/coolservice/v2/00'.
Found node type 'Element' with name 's:Fault' and namespace 'http://schemas.xmlsoap.org/soap/envelope/'&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Hmm, it's getting the fault, but can't seem to handle it. I tried adding typed faults
to my WCF contract, but the SL WCF stack doesn't have the FaultContractAttribute.
It appears as if SL cannot read faults at all.
&lt;/p&gt;
&lt;p&gt;
Enter HackFaults. That message provides two pieces of data from the SOAP message,
the element name, and the namespace. We can hijack these to pass our fault information,
then extract it from the exception message. H to the A to the C-K-Y.
&lt;/p&gt;
&lt;p&gt;
First off, we need to get access to our WCF fault. We can do this with an System.ServiceModel.Dispatcher.IErrorHandler.
I've attached the full code, but basically you add an attribute to your WCF service
to wire up the error handler. If you're doing WCF work, you&amp;nbsp;probably want this
anyways for logging purposes and so on. I've attached the entire error handler code
to this article. The real meat of the error handler is this little function:
&lt;/p&gt;
&lt;p&gt;
&lt;font size=3&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; ProvideFault(Exception
error, MessageVersion version, &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ref&lt;/span&gt; Message
fault)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
HackFaults store the exception in the httpcontext&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; var context &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; System.Web.HttpContext.Current;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (context
!&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;)
{ 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
Only works in AspNetCompat mode&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (!context.Request.Browser.Crawler
&amp;amp;&amp;amp; context.Request.Browser.EcmaScriptVersion.Major &amp;gt; 0) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
This should rule out non-browsers&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; context.Items.Add(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"HackFault"&lt;/span&gt;,
error);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;br&gt;
&lt;/span&gt;
&lt;/p&gt;
&gt; 
&lt;p&gt;
I'm not sure if there's a better way to differentiate between browsers and real SOAP
stacks. If there is let me know. Now, in our Global.asax, we want to pick this information
up and replace the actual SOAP fault with our own hackfault:
&lt;/p&gt;
&lt;pre&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;protected&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;void&lt;/span&gt; Application_EndRequest(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;object&lt;/span&gt; sender,
EventArgs e) { &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
In all fairness, I was drinking eiswein at the time&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (Context.Items.Contains(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"HackFault"&lt;/span&gt;))
{ Context.Response.ContentType &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"text/xml"&lt;/span&gt;;
Context.Response.StatusCode &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; 200;
Context.Response.ClearContent(); var hackEx &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; Context.Items[&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"HackFault"&lt;/span&gt;] &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;as&lt;/span&gt; Exception;
var hackFaultXml &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt;.Format( &lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"&amp;lt;s:Envelope
xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"&amp;gt;&amp;lt;s:Body&amp;gt;&amp;lt;{0} xmlns=\"{1}\"
/&amp;gt;&amp;lt;/s:Body&amp;gt;&amp;lt;/s:Envelope&amp;gt;"&lt;/span&gt;, hackEx.GetType().ToString(), Context.Server.HtmlEncode(hackEx.Message));
Context.Response.Output.Write(hackFaultXml); } } &lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
Now we have a message that has the bits of data we care about in the right places
for the Silverlight exception to be ready for parsing.&amp;nbsp;The&amp;nbsp;SL-side parsing
code is vile but easy:
&lt;/p&gt;
&lt;pre&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;static&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt; ExtractHackFaultMessage(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;this&lt;/span&gt; Exception
ex) { &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
HackFaults generate these Exceptions and messages:&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//Without
debug:&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//Could
not connect to server: System.Runtime.Serialization.SerializationException: [SFxInvalidMessageBody]&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//Arguments:FaultException,Something
silly&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//With
debug:&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//Could
not connect to server: System.Runtime.Serialization.SerializationException: 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;OperationFormatter
encountered an invalid Message body. Expected to find node type 'Element' with 
&lt;br&gt;
name 'SomeOperationResponse' and namespace 'http://schemas.cool.com/yea/v2/00'. 
&lt;br&gt;
Found node type 'Element' with name 'FaultException' and namespace 'Something silly'&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (!(ex &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;is&lt;/span&gt; System.Runtime.Serialization.SerializationException)) &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;return&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;;
var msg &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; ex.Message; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;string&lt;/span&gt; regexp; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (msg.Contains(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"[SFxInvalidMessageBody]"&lt;/span&gt;))
{ regexp &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;@"Arguments:(.*),(.*)"&lt;/span&gt;;
} &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;else&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (msg.Contains(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"OperationFormatter
encountered an invalid Message body"&lt;/span&gt;)) { regexp &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;@"Found
node type 'Element' with name '(.*)' and namespace '(.*)'"&lt;/span&gt;; } &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;else&lt;/span&gt; { &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
Nope, it's some thing else&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;return&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;;
} var match &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; System.Text.RegularExpressions.Regex.Match(msg,
regexp); &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (match.Groups.Count
!&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; 3) &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;return&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;null&lt;/span&gt;; &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;//
Not expected&lt;/span&gt; var exType &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; match.Groups[1].Value.Trim();
var exMsg &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; match.Groups[2].Value.Trim(); &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;if&lt;/span&gt; (exType
== &lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"System.ServiceModel.FaultException"&lt;/span&gt;) &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;return&lt;/span&gt; exMsg; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;else&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;return&lt;/span&gt; exType+ &lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;":
"&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;+&lt;/span&gt; exMsg;
}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
This little function will give me the fault information (and not mention FaultException
if that's what it is) or null if it can't extract it. When dealing with errors, I
can show an error&amp;nbsp;like this: "Error: " + (ex.ExtractHackFaultMessage() ?? ex.ToString())
&lt;/p&gt;
&lt;p&gt;
This gives me at least rudimentary error reporting from the server back to Silverlight.
If this can be improved or fixed up, please tell me. (Typed fault exceptions would
be nice, but then SL can't codegen the contracts.) At any rate, it works as a cheap
hack until Silverlight Beta 2 (they gotta fix it by then, right? Right?).
&lt;/p&gt;
&lt;a href="http://www.atrevido.net/blog/content/binary/HttpErrorHandler.cs.txt"&gt;HttpErrorHandler.cs.txt
(2.49 KB)&lt;/a&gt;&lt;img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=ffa70c25-0c78-474b-8d60-10a693ffc407" /&gt;</description>
      <comments>http://www.atrevido.net/blog/CommentView,guid,ffa70c25-0c78-474b-8d60-10a693ffc407.aspx</comments>
      <category>Code</category>
    </item>
    <item>
      <trackback:ping>http://www.atrevido.net/blog/Trackback.aspx?guid=7961bd99-f48a-4d9a-a13c-b7ba9c07ff61</trackback:ping>
      <pingback:server>http://www.atrevido.net/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.atrevido.net/blog/PermaLink,guid,7961bd99-f48a-4d9a-a13c-b7ba9c07ff61.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.atrevido.net/blog/CommentView,guid,7961bd99-f48a-4d9a-a13c-b7ba9c07ff61.aspx</wfw:comment>
      <wfw:commentRss>http://www.atrevido.net/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=7961bd99-f48a-4d9a-a13c-b7ba9c07ff61</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <strong>Nothing surprising</strong>
        </p>
        <p>
I've been waiting for this: <a href="http://www.nytimes.com/2008/03/12/business/12heart-web.html?_r=2&amp;ref=technology&amp;oref=slogin&amp;oref=slogin">http://www.nytimes.com/2008/03/12/business/12heart-web.html?_r=2&amp;ref=technology&amp;oref=slogin&amp;oref=slogin</a></p>
        <p>
Certain pacemakers (Medtronic in this case) are easy to reprogram without any useful
authentication. The result is that an attacker can kill someone remotely by modifying
their pacemaker. 
</p>
        <p>
This certainly will not be the first time this happens. The response from Medtronic
is idiotic:
</p>
        <p>
"<em>To our knowledge there has not been a single reported incident of such an event
in more than 30 years of device telemetry use, which includes millions of implants
worldwide</em>"
</p>
        <p>
It's funny seeing industries that typically have little to no security requirements
in their products get rudely awakened. Another vendor, St. Jude, says something equally
scary:
</p>
        <p>
"<em>used “proprietary techniques” to protect the security of its implants and had
not heard of any unauthorized or illegal manipulation of them</em>"
</p>
        <p>
Who wants to bet there's some globally shared key at work? At any rate, we expected
this kind of stuff because too many people can't think clearly about security (I'll
be writing about [the lack of] VoIP security soon). 
</p>
        <p>
          <strong>A growing problem</strong>
        </p>
        <p>
How should these devices secured in the first place? I'm not talking specifically
about pacemakers, but all sorts of implants and enhancements that we will have
during the next years, using security technology today.
</p>
        <p>
First, they need to be remotely monitored. This is relatively easy to secure, as the
risk is considerably less: information disclosure. For example, if each monitoring
device had to have it's public key explicitly trusted for a particular patient, that'd
be pretty easy. In the case that a key was disclosed (say, by capturing and attacking
a monitoring device), the only access gained is read-only. 
</p>
        <p>
Making it even less risk, it's possible that the amount of effort required for such
an attack exceeds the value of the information gained. For example, if an attacker
can access a target's house, they could steal identification and request medical records
be sent to them. 
</p>
        <p>
More importantly is editing of configuration. How do we determine who has access?
In theory, we want any qualified medical professional to be able to change configuration
in case of an emergency. Without a global network connected to the device, the device
has no way to validate credentials, particularly revocation. Additionally, even assuming
that every device has access to a global database, there would be too many authorised
users to ensure security. (Just like large government databases.)
</p>
        <p>
Is this a threat? Some people may think this is a far fetched idea. Certainly today
this is not a widespread fear. It may be a neat way to carry off a attack against
a single target, but I doubt it'd be effective for major attacks. But how long will
it be until a large percentage of the population carries some kind of embedded device?
Pacemakers, medicine delivery systems, vision implants, hearing, digestive -- the
list goes on. 
</p>
        <p>
The bottom line is that humans will carry more embedded technology, and this technology
must be secure *and* accessible. A system where losing your private key means surgery
is not usuable.
</p>
        <p>
          <strong>The easy solution</strong>
        </p>
        <p>
As far as I can tell, the only solid way to ensure security with today's technology
is to add a hard link. In order for anyone to modify configuration, the configuration
device must establish itself over a physical connection. This ensures no remote attacks
are possible. This would take away little to no convenience -- before editing yourself,
you'd have to let them physically connect a device to you. 
</p>
        <p>
The same could be done for remote devices. Let's say your doctor wants to adjust your
body remotely. You'd simply key the remote device[s] to your doctor, and key yourself
to the remote device[s]. You've established a chain of trust that's easy to clear
and recreate later. There is no global database, simply yourself and devices you touch. 
</p>
        <p>
This mimics what you have in the real world: You trust your doctor after you establish
a relationship with him. You can then call him on the phone and you trust his advice
to take more or less of the medicine. 
</p>
        <p>
A quick note on the details: The medical devices themselves don't need hard lines
to the hard configuration interface. Indeed, your "hard link" could be a special device
keyed to yourself. However, embedding this device into the body means you won't lose
it and it'll be readily accessible to medical teams, even if you're unconscious. 
</p>
        <p>
To protect against damage to the hard link device, I suppose a backup key could be
made authorized. You could then store it safe, by yourself (as in, with a bank's security
deposit box, <em>not</em> the database of the device manufacturer). 
</p>
        <p>
          <strong>The general solution</strong>
        </p>
        <p>
However, this only secures us as much as we can trust the authentication. But it still
relies on manual revocation and trust editing. It may be acceptable to Verisign when
they accidentally issue a certificate in Microsoft's name to an attacker, but it is
not acceptable for humans. Specifically, in a short vulnerability window, you could
die. 
</p>
        <p>
The real solution, and one that we're going to need eventually across all technology,
is intelligence. Specifically, a machine intelligence that determines if what is happening
or what is requested is dangerous. This is the only way that we will have security
moving forward. 
</p>
        <p>
This kind of intelligence is what we use to protect ourselves now. If the water comes
out glowing green, we decide we won't trust it, even though we do trust (in general)
our public water system. If you see your doctor and he recommends moving from 5mg
to 500mg of Xanax a day, you'll immediately revoke his trust. 
</p>
        <p>
Attacks will adopt this kind of intelligence. A hacker uses a vulnerability to gain
access and then attack other systems from there. How long will it be until attacking
programs themselves replace the work done by the hacker? 
</p>
        <p>
Our software and machines will have to adopt this kind of intelligence to thwart such
attacks. It will no longer be "oh, sorry you got hit by malicious code from clicking
on a hyperlink, please reinstall your OS". As long as humans can be killed by the
devices in use, the stakes are too high for even tiny vulnerability windows.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.atrevido.net/blog/aggbug.ashx?id=7961bd99-f48a-4d9a-a13c-b7ba9c07ff61" />
      </body>
      <title>Medical and General Security</title>
      <guid isPermaLink="false">http://www.atrevido.net/blog/PermaLink,guid,7961bd99-f48a-4d9a-a13c-b7ba9c07ff61.aspx</guid>
      <link>http://www.atrevido.net/blog/2008/03/12/Medical+And+General+Security.aspx</link>
      <pubDate>Wed, 12 Mar 2008 23:56:44 GMT</pubDate>
      <description>&lt;p&gt;
&lt;strong&gt;Nothing surprising&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
I've been waiting for this: &lt;a href="http://www.nytimes.com/2008/03/12/business/12heart-web.html?_r=2&amp;amp;ref=technology&amp;amp;oref=slogin&amp;amp;oref=slogin"&gt;http://www.nytimes.com/2008/03/12/business/12heart-web.html?_r=2&amp;amp;ref=technology&amp;amp;oref=slogin&amp;amp;oref=slogin&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Certain pacemakers (Medtronic in this case) are easy to reprogram without any useful
authentication. The result is that an attacker can kill someone remotely by modifying
their pacemaker. 
&lt;/p&gt;
&lt;p&gt;
This certainly will not be the first time this happens. The response from Medtronic
is idiotic:
&lt;/p&gt;
&lt;p&gt;
"&lt;em&gt;To our knowledge there has not been a single reported incident of such an event
in more than 30 years of device telemetry use, which includes millions of implants
worldwide&lt;/em&gt;"
&lt;/p&gt;
&lt;p&gt;
It's funny seeing industries that typically have little to no security requirements
in their products get rudely awakened. Another vendor, St. Jude, says something equally
scary:
&lt;/p&gt;
&lt;p&gt;
"&lt;em&gt;used “proprietary techniques” to protect the security of its implants and had
not heard of any unauthorized or illegal manipulation of them&lt;/em&gt;"
&lt;/p&gt;
&lt;p&gt;
Who wants to bet there's some globally shared key at work? At any rate, we expected
this kind of stuff because too many people can't think clearly about security (I'll
be writing about [the lack of] VoIP security soon). 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;A growing problem&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
How should these devices secured in the first place? I'm not talking specifically
about pacemakers, but all sorts of implants&amp;nbsp;and enhancements that we will have
during the next years, using security technology today.
&lt;/p&gt;
&lt;p&gt;
First, they need to be remotely monitored. This is relatively easy to secure, as the
risk is considerably less: information disclosure. For example, if each monitoring
device had to have it's public key explicitly trusted for a particular patient, that'd
be pretty easy. In the case that a key was disclosed (say, by capturing and attacking
a monitoring device), the only access gained is read-only. 
&lt;/p&gt;
&lt;p&gt;
Making it even less risk, it's possible that the amount of effort required for such
an attack exceeds the value of the information gained. For example, if an attacker
can access a target's house, they could steal identification and request medical records
be sent to them. 
&lt;/p&gt;
&lt;p&gt;
More importantly is editing of configuration. How do we determine who has access?
In theory, we want any qualified medical professional to be able to change configuration
in case of an emergency. Without a global network connected to the device, the device
has no way to validate credentials, particularly revocation. Additionally, even assuming
that every device has access to a global database, there would be too many authorised
users to ensure security. (Just like large government databases.)
&lt;/p&gt;
&lt;p&gt;
Is this a threat? Some people may think this is a far fetched idea. Certainly today
this is not a widespread fear. It may be a neat way to carry off a attack against
a single target, but I doubt it'd be effective for major attacks. But how long will
it be until a large percentage of the population carries some kind of embedded device?
Pacemakers, medicine delivery systems, vision implants, hearing, digestive -- the
list goes on. 
&lt;/p&gt;
&lt;p&gt;
The bottom line is that humans will carry more embedded technology, and this technology
must be secure *and* accessible. A system where losing your private key means surgery
is not usuable.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;The easy solution&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
As far as I can tell, the only solid way to ensure security with today's technology
is to add a hard link. In order for anyone to modify configuration, the configuration
device must establish itself over a physical connection. This ensures no remote attacks
are possible. This would take away little to no convenience -- before editing yourself,
you'd have to let them physically connect a device to you. 
&lt;/p&gt;
&lt;p&gt;
The same could be done for remote devices. Let's say your doctor wants to adjust your
body remotely. You'd simply key the remote device[s] to your doctor, and key yourself
to the remote device[s]. You've established a chain of trust&amp;nbsp;that's easy to clear
and recreate later. There is no global database, simply yourself and devices you touch. 
&lt;/p&gt;
&lt;p&gt;
This mimics what you have in the real world: You trust your doctor after you establish
a relationship with him. You can then call him on the phone and you trust his advice
to take more or less of the medicine. 
&lt;/p&gt;
&lt;p&gt;
A quick note on the details: The medical devices themselves don't need hard lines
to the hard configuration interface. Indeed, your "hard link" could be a special device
keyed to yourself. However, embedding this device into the body means you won't lose
it and it'll be readily accessible to medical teams, even if you're unconscious. 
&lt;/p&gt;
&lt;p&gt;
To protect against damage to the hard link device, I suppose a backup key could be
made authorized. You could then store it safe, by yourself (as in, with a bank's security
deposit box, &lt;em&gt;not&lt;/em&gt; the database of the device manufacturer). 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;The general solution&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
However, this only secures us as much as we can trust the authentication. But it still
relies on manual revocation and trust editing. It may be acceptable to Verisign when
they accidentally issue a certificate in Microsoft's name to an attacker, but it is
not acceptable for humans. Specifically, in a short vulnerability window, you could
die. 
&lt;/p&gt;
&lt;p&gt;
The real solution, and one that we're going to need eventually across all technology,
is intelligence. Specifically, a machine intelligence that determines if what is happening
or what is requested is dangerous. This is the only way that we will have security
moving forward. 
&lt;/p&gt;
&lt;p&gt;
This kind of intelligence is what we use to protect ourselves now. If the water comes
out glowing green, we decide we won't trust it, even though we do trust (in general)
our public water system. If you see your doctor and he recommends moving from 5mg
to 500mg of Xanax a day, you'll immediately revoke his trust. 
&lt;/p&gt;
&lt;p&gt;
Attacks will adopt this kind of intelligence. A hacker uses a vulnerability to gain
access and then attack other systems from there. How long will it be until attacking
programs themselves replace the work done by the hacker? 
&lt;/p&gt;
&lt;p&gt;
Our software and machines will have to adopt this kind of intelligence to thwart such
attacks. It will no longer be "oh, sorry you got hit by malicious code from clicking
on a hyper