Logo




Subscribe:
RSS 2.0 | Atom 1.0
Categories:

Sign In


[Giagnocavo]Michael::Write()

# Thursday, June 26, 2008
I underestimated the power of query comprehensions

In my last post, 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...

...But... C# still can't do discriminated unions efficiently or effectively ;).


    1 // crudcreatecompare.cs: Generates LINQ CRUD table fields using the horribly named DatabaseBase code

    2 //

    3 // Tables look like: [Table(Name="dbo.Accounts")]

    4 // Columns look like this:

    5 //  [Column(Storage="_AccountName", DbType="VarChar(128) NOT NULL", CanBeNull=false, IsPrimaryKey=true)]

    6 //  [DataMember(Order=1)] // Exists if serialization is turned on; used to order key parameters

    7 // Emits:

    8 //  public static readonly TableHelper<Account, String> Accounts =

    9 //      CreateTable(dc => dc.Accounts, a => a.AccountName);

   10 

   11 using System;

   12 using System.Collections.Generic;

   13 using System.Data.Linq.Mapping;

   14 using System.IO;

   15 using System.Linq;

   16 using System.Reflection;

   17 using System.Runtime.Serialization;

   18 

   19 class Program

   20 {

   21     static void Main()

   22     {

   23         Console.WriteLine(

   24             new Program().generate(

   25             "C:\\yourlinq.dll"));

   26     }

   27 

   28     string generate(string asmpath)

   29     {

   30         var asm = Assembly.LoadFrom(asmpath);

   31         var lines = from t in asm.GetExportedTypes()

   32                     let ta = getAttr<TableAttribute>(t)

   33                     where ta != null

   34                     let name = pluralize(ta.Name.Replace("dbo.", ""))

   35                     orderby name

   36                     select genTable(t, name);

   37         return joinStrings("", lines);

   38     }

   39 

   40     string genTable(Type t, string tableName)

   41     {

   42         var keyProps =

   43             from p in t.GetProperties()

   44             let c = getAttr<ColumnAttribute>(p)

   45             where c != null && c.IsPrimaryKey

   46             let dm = getAttr<DataMemberAttribute>(p)

   47             orderby dm == null ? 0 : dm.Order

   48             select p;

   49         var tw = new StringWriter();

   50         tw.WriteLine("public static readonly TableHelper<{0}, {1}> {2} =",

   51             t.Name,

   52             joinStrings(", ", keyProps.Select(p => p.PropertyType.Name)),

   53             tableName);

   54         tw.WriteLine("\tCreateTable(dc => dc.{0}, {1});",

   55             tableName,

   56             joinStrings(", ", keyProps.Select(p => "a => a." + p.Name)));

   57         tw.WriteLine();

   58         return tw.ToString();

   59     }

   60 

   61     string joinStrings(string sep, IEnumerable<string> items)

   62     {

   63         return string.Join(sep, items.ToArray());

   64     }

   65     string pluralize(string s)

   66     {

   67         return s.EndsWith("s") ? s : s + "s";

   68     }

   69 

   70     T getAttr<T>(ICustomAttributeProvider icap)

   71     {

   72         var a = icap.GetCustomAttributes(typeof(T), true);

   73         return a.Length == 0 ? default(T) : (T)a[0];

   74     }

   75 }

Code | FSharp
Thursday, June 26, 2008 6:15:10 AM UTC  #    Comments [0]  |  Trackback

OpenID
Please login with either your OpenID above, or your details below.
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview