Monthly Archives: March 2009

Problem with the ETag code in my book

I just discovered that in Chapter 11 – my code for generating ETags has a bug.  The code needs to wrap the ETag in a set of quotes:

string GenerateETag(User u)
{
    byte[] bytes = Encoding.UTF8.GetBytes(u.UserId + u.LastModified.ToString());
    byte[] hash = MD5.Create().ComputeHash(bytes);
    string etag = Convert.ToBase64String(hash);
    return string.Format(""{0}"", etag);
}
Sorry – as I always say “Hi – I’m Jon, I’m a developer, and I write code with bugs” ;)

New version of the REST starter kit

Its available now on Codeplex  – I showed off both the client and server pieces of the starter kit at my full-day REST seminar at SDWest this week.   There are some very useful features in the kit like:

  • WebProtocolException and an IErrorHandler implementation that returns correct error codes
  • The HttpClient class and the “Paste as Xml Serializable” feature to help minimize the work necessary when building RESTful clients

Those are just two of my favorites but there are a lot more.  I’ll be using the HttpClient to help do Conditional GET when I do my Caching in REST talk next Friday at Mix!  If you are going to be in Vegas – some by and say hello.

Programming against M

Over on the Oslo forums there have been a few questions about how to interact with M (specifically MSchema) programmatically.  I’ve been doing this quite a bit creating PluralSight’s Oslo course, as well as working on various samples.

What I’m going to do is create an in-memory representation of one or more M files by using the M Compiler – which is clearly named as Compiler (it in the Microsoft.M namespace).  Compiler has a couple of methods, one is aptly named Compile, which I’m not going to use in this sample.  Compile creates a  CompilationResults object that not only has the in-memory parsed representation of the MSchema, it also has the in-memory representation of the Database that would be created if you used mx.exe to deploy the M to the database.

Instead I’m going to use Compiler.Parse, because I’m only interested in the M in-memory representations at the moment (not the database objects).  I need to reference three assemblies to get this to work: System.Xaml.dll, System.DataFlow.dll, and Microsoft.M.Framework.dll. To get Compiler to be happy, I have to pass it a CompilerOptions object which is essentially the arguments to the compiler.   I’m going to actually parse the provided M sources in the SDK for the Repository itself (found in the OSLOInstallDirModels directory as raw M files with a M project thrown in as well). 

string dir = @"C:Program Files (x86)Microsoft Oslo SDK 1.0Models";
CompilerOptions cops = new CompilerOptions();
cops.IncludeStandardLibrary = true;
foreach (string file in Directory.GetFiles(dir, "*.m", SearchOption.AllDirectories))
{
    CompilerInput cinput = new CompilerInput();
    cinput.Name = Path.GetFileNameWithoutExtension(file);
    cinput.Reader = new StreamReader(file, Encoding.UTF8, true);
    cops.Sources.Add(cinput);
}

CompilationResults cresults = Compiler.Parse(cops);

After I get the CompilationResults back, I can loop and party on the CompilationResults.ParsedSources.Modules collection.  This will be the collection of MSchema modules found in the source directory.

To get at the actual M artifacts,  for each Module I need to loop its Members property.  Members is of type ICollection.  IDeclaration is the interface that all Module members implement.  If I use Reflector (such a handy tool) I can see all the types that implement this interface:

idecs

I put a red arrow next to the two really interesting implementations – ExtentDeclaration and TypeDeclaration.   If I had the following M,  I’d get one of each object:

module MFun
{
   type foo : {
    id : Integer32 = AutoNumber();
    data : Text;
} where identity id;

   foos : foo*;
}

In this case foo is a TypeDeclaration, and foos is an ExtentDeclaration.  This example is pretty easy, but because MSchema is flexible, things can get ugly very quickly.

Where things get ugly is when you want to follow the trail further than just the top level object.  What if for example I wanted to find out the definition for each ExtentDeclaration. Let me take another example:

module Models1
{
    Model :
    {
        Id : Integer64 = AutoNumber();
        Name : Text;
    }* where identity Id;
}
module Models2
{
    Model :(
    {
        Id : Integer64 = AutoNumber();
        Name : Text;
    } where identity Id)*;
}

In this sample I’d have two Modules – each with a single ExtentDeclaration.  But the first ExtentDeclaration’s Type property is a ParamaterizedExpression.  A ParameterizedExpression has an Arguments collection, and that’s where you can get back to the actual definition.  In this case its ParameterizedExpression is made up of two arguments: one is a CollectionType that shows me the {Id, Name} structure, and the other is another ParamaterizedExpression that is the definition of the where statement.  The second Module (Models2) has a single ExtentDeclaration, but its Type is Collection (because of the parenthesis and the way the MSchema is parsed).  At the end of the day these two extents really are the *same* semantically – but because of the slightly different syntax – the object model ends up looking different.

If I where to parse my “foo” example,  I’d end up with one Module with two members, and if I wanted to figure out where the definition of the ExtentDeclaration came from,  I’d have to go down the object model until I found the type declaration for the collection type that foos is made up of.

types

Here is some code (included in the project you can download at the end) that finds the type name for every ExtentDeclaration in a Module, at least using all the various M sources I have :)  (That is – it works on my machine).

public static string FindExtentTypeName(ExtentDeclaration extent)
     {
         string name = "Not Found";
         var et = extent.Type as Microsoft.M.CollectionType;
         if (et != null)
         {
             if (et.ElementType is ParameterizedExpression)
             {
                 var theExpression = et.ElementType as ParameterizedExpression;
                 //check to see if expression refers to a type
                 var results = (from arg in theExpression.Arguments
                                where arg.GetType() == typeof(DeclarationReference)
                                select arg);
                 if (results != null && results.Count() > 0)//we have an extent
                 {
                     var dr = results.First() as DeclarationReference;
                     if (dr != null)
                     {
                         name = dr.Name;

                     }
                 }
                 else
                 {

                     name= extent.Name.Value;

                 }
             }//direct extent
             if (et.ElementType is DeclarationReference)
             {

                 name = ((DeclarationReference)et.ElementType).Name;

             }
         }
         else
         {
             var parm = extent.Type as ParameterizedExpression;
             if (parm != null)
             {
                 CollectionType collectionType = (from ex in parm.Arguments
                                                  where ex.GetType() == typeof(CollectionType)
                                                  select ex).First() as CollectionType;
                 if (collectionType.ElementType is EntityType)
                 {
                     name = extent.Name.Value;

                 }
                 if (collectionType.ElementType is DeclarationReference)
                 {
                     name = ((DeclarationReference)collectionType.ElementType).Name;

                 }
             }
         }
         return name;
     }

 }

So the output looks like this:

output

 

Happy M parsing.

ProgrammingM.zip (16.12 KB)