Windows Phone 7 and SkyDrive Integration

I like my Windows Phone 7, but I love its support for One Note and SkyDrive.

Getting it all to work

However the whole integration story is a bit temperamental.  Here are my tips for getting everything to work nicely together on the phone, in the SkyDrive web editor, and in Office on the desktop:

  1. If you’ve got yourself in a mess, reset Office on the phone.  I’ve done this several times with minimum pain.  Use Settings –> Applications –> Office –> Reset Office.
  2. When you set up Office on the phone it creates a One Note notebook called Personal (Web) inside the Documents folder in SkyDrive.  Don’t rename it.  Don’t move it.  Renaming is the obvious one – it will break the link.  But I thought it would be OK to move it.  It isn’t.  I did so and it worked great for a bit, but the next time I reset Office on the phone it created a new one in the Documents folder and linked to that one instead.  Pain.  Incidentally, it’s completely safe to reset Office when the Documents\Personal (Web) notebook exists and has content – it preserves all existing notes and sections.
  3. When you reset Office on the phone it creates rather boring “Explore Microsoft …” documents.  It looks at first like you can’t delete them, but in fact the Word / Excel / Powerpoint ones are in the “Phone” location in the “locations” area.  If you touch and hold them in there you can delete them.  The OneNote one is in your Personal (Web) folder and is easy to delete in there.

What’s in the Launch Area?

This is what I’m calling the home screens in Office on the phone that show you the tiles.  There is one for notes, and another for documents.  How does the phone decide what tiles to show?

Both OneNote and Word / Excel scan SkyDrive when you setup or reset Office in order to populate this area.  OneNote scans down through all SkyDrive folders looking for notebooks, while for other documents only the top level folder in SkyDrive is scanned.  In both areas the first 16 notes / documents it finds are displayed.

After that anything you view or edit on your phone is added to the notes or documents area – it becomes a most recently used feature.  The limit remains 16 documents.

So if you create a note or document on your phone it appears here, but notes or documents you create in SkyDrive on another computer don’t appear here until you navigate to them and open them (by going to the locations / SkyDrive link in the Office app).

Where is my document stored when I create it on the phone?

  • OneNote puts all new notes in the SkyDrive / Documents / Personal (Web) / Unfiled Notes section
  • Word and Excel put all documents in the root of SkyDrive

How do I organise OneNote?

Unfiled Notes

Your phone will create new note pages in the “Unfiled Notes” section of the Personal IWeb) notebook.  But if you have a lot of notes you won’t want to keep them there.

I recommend moving them.  First, open SkyDrive in the browser.  Then click on “Open in OneNote”.  Using the desktop app create new sections in the Personal (Web) notebook (e.g. Home, Work etc) then move your unfiled notes into them.  As far as I can tell only the desktop app allows you to move notes around, the web interface doesn’t support this.

Once you’ve moved them they are still viewable and editable on the phone.  But notes you create on the phone will always go into “Unfiled Notes”.  There’s no way of adding notes to a specific section from the phone.

So what have I got at the end of all this?

  • Whatever system you use, Getting Things Done or (my favourite) Getting Results the Agile Way you can create and manage daily / weekly / monthly lists on your phone.
  • The lists sync automatically to SkyDrive, and you can do more advanced juggling on OneNote on your desktop.
  • You can keep trivial spreadsheets such as paying in / expenses on your phone and sync / edit them in the same way.
  • Now I know there are lots of competing apps and cloud solutions for all this, but MIcrosoft have very nearly got this one right.  Maybe with Windows Phone 8 there will finally be a cohesive story.

Oracle Linked Server from SQL Express 2005

Using SQL Server Management Studio to set up an Oracle Linked Server.

When setting up a linked server to Oracle from a SQL Express 2005 instance using the OraOLEDB.Oracle OLE DB Provider you need to be able to change the “AllowInProcess” property to true from the provider properties. Or it doesn’t work.

Problem… when connecting to a SQL Express 2005 instance there is no properties dialog available for the provider.

Solution:

EXEC sp_MSset_oledb_prop N’OraOLEDB.Oracle’, N’AllowInProcess’, 1

in the master database.

SQL Server Isolation Levels

I keep deleting this then needing it again, so here it is!  It needs an update to discuss snapshot isolation ‘though.

Thanks to Andy Grout for working this stuff out with me…

All isolation levels affect the way in which you read data. They also affect the way others can update data because the type and duration of the locks differ.

Read Uncommitted

  • Takes out no locks when issuing SELECT statements
  • So you can read other transactions’ uncommitted data i.e. dirty reads

Read Committed

  • Prevents dirty reads
  • Takes out a shared lock when issuing a SELECT statement (this prevents updates)
  • If another transaction has an exclusive lock your SELECT will block until the other completes
  • Releases the shared lock when the SELECT completes, not when the tranaction completes
  • So the same SELECT later on in the same transaction might return different data i.e. non-repeatable reads

Repeatable Read

  • Prevents dirty reads and non-repeatable reads
  • Takes out shared locks when issuing SELECT statements and doesn’t release them until the transaction ends
  • So prevents any data you read from changing via updates or deletes
  • But doesn’t prevent new rows from being inserted into other pages
  • So your SELECT statement might still return more rows the second time you execute it i.e. phantom rows

Serializable

  • Prevents dirty reads, non-repeatable reads and phantom rows
  • In SQL 2000 and SQL 2005 takes out key-range locks, a special type of shared lock which prevents inserts into a range of values
  • Ensures a SELECT statement always returns the same results within a transaction

Digging around: Analysing ASP.NET MVC2 FastTrack expressions

This is a third companion post to Scott Guthrie’s ASP.NET MVC 2: Strongly Typed Html Helpers.

Today instead of reading code, I’d thought I’d write some. I threw together a class which does the analysis performed by the FastTrack class in ASP.NET MVC2. To recap – the FastTrack class:

  • decides if an expression can be “fast tracked”
  • if it can – builds, compiles and caches it
  • returns the cached expression in future calls

This code demonstrates the bit that does the deciding, and gives us something to play around with.

using System;
using System.Linq.Expressions;

namespace MvcHarness
{
  public class FastTrackAnalyser<TModel>
  {
    public void Analyse<TValue>(Expression<Func<TModel, TValue>> lambda)
    {
      ParameterExpression modelParameter = lambda.Parameters[0];
      Expression body = lambda.Body;

      if (modelParameter == body)
      {
        Console.WriteLine("{0} is a function returning its own argument", lambda);
        return;
      }

      ConstantExpression constantExpression = body as ConstantExpression;
      if (constantExpression != null)
      {
        Console.WriteLine("{0} is a function returning a constant value", lambda);
        return;
      }

      MemberExpression memberExpression = body as MemberExpression;
      if (memberExpression != null)
      {
        if (memberExpression.Expression == null)
        {
          Console.WriteLine("{0} is a function returning a static member of either the model or another type", lambda);
          return;
        }

        if (memberExpression.Expression == modelParameter)
        {
          Console.WriteLine("{0} is a function returning a member of the model", lambda);
          return;
        }

        ConstantExpression constantExpression2 = memberExpression.Expression as ConstantExpression;
        if (constantExpression2 != null)
        {
          Console.WriteLine("{0} is a function representing a captured local variable", lambda);
          return;
        }
      }
      Console.WriteLine("{0} cannot be fast tracked", lambda);
    }
  }
}


I called it like this (with output inline in the comments):

using System;

namespace MvcHarness
{
  class Program
  {
    static void Main(string[] args)
    {
      FastTrackAnalyser<string> analyser = new FastTrackAnalyser<string>();

      analyser.Analyse(x => x);
      // outputs "x => x is a function returning its own argument"

      analyser.Analyse(x => 999);
      // outputs "x => 999 is a function returning a constant value"

      analyser.Analyse(x => String.Empty);
      // outputs "x => String.Empty is a function returning a static member of either the model or another type"

      analyser.Analyse(x => x.Length);
      // outputs "x => x.Length is a function returning a member of the model"

      string name = "Joe Field";
      analyser.Analyse(x => name);
      // outputs "x => value(MvcHarness.Program+<>c__DisplayClass0).name is a function representing a captured local variable"

      analyser.Analyse(x => name.Length);
      // outputs "x => value(MvcHarness.Program+<>c__DisplayClass0).name.Length cannot be fast tracked"
    }
  }
}

The really interesting calls are the last two. They are analysing expressions which use captured local variables. The first one succeeds, but the second fails because it attempts to access a member of the variable.

Digging around: FastTrack in ASP.NET MVC 2

This is a second companion post to Scott Guthrie’s ASP.NET MVC 2: Strongly Typed Html Helpers.

In my previous post I drilled down into the code executed when ASP.NET MVC 2 turned:

<%= Html.TextBoxFor(model => model.ProductName) %>

into:

<input id="ProductName" name="ProductName" type="text" value="Aniseed Syrup" />

We found that in order to do it ASP.NET MVC had performed two distinct operations:

  1. parsed the expression tree produced by the compiler for model => model.ProductName to extract the name of the property ("ProductName") to use in the id and name attributes of the input element
  2. compiled the expression and invoked the resulting delegate to produce the "Aniseed Syrup" value

Having examined the first case I started looking at how the expression was compiled into an executable delegate.

At this point we ran into this line of code:

return CachedExpressionCompiler.Process(expression)(container);

The problem

MVC is faced with a dilemma. It wants to use expression trees rather than delegates.

It likes to use the metadata obtained from the expression to, amongst other things, extract the property name.

But compiling expression trees is expensive.

To get round this problem it maintains an in-process cache of compiled expressions.

Disclaimer – this is a simple case

We are only going to look at the simple property access case:

model => model.ProductName

If we didn’t we would vanish into CachedExpressionCompiler for a long time. Many different types of expressions are compiled and cached, using different strategies.

By only looking at the property access case we will be able to visit the main classes, in particular FastTrack<TModel, TValue>.  We can look at the other caching strategies another time.

CachedExpressionCompiler.Process method

Here’s the CachedExpressionCompiler.Process() method in full – the comment describes it way better than I just did:

// This is the entry point to the cached expression tree compiler. The processor will perform a series of checks 
// and optimizations in order to return a fully-compiled func as quickly as possible to the caller. If the 
// input expression is particularly obscure, the system will fall back to a slow but correct compilation step. 
public static Func<TModel, TValue> Process<TModel, TValue>(Expression<Func<TModel, TValue>> lambdaExpression) { 
    return Processor<TModel, TValue>.GetFunc(lambdaExpression); 
} 

and here’s the beginning of Processor.GetFunc():

public static Func<TModel, TValue> GetFunc(Expression<Func<TModel, TValue>> lambdaExpression) { 
    // look for common patterns that don't need to be fingerprinted 
    Func<TModel, TValue> func = GetFuncFastTrack(lambdaExpression); 
    if (func != null) { 
        return func; 
    } 
... 
... 
... 
}

We’ll talk about fingerprinting another day. Suffice it to say that the call to GetFuncFastTrack() succeeds for our expression and we need go no further.

Here’s the whole of Processor.GetFuncFastTrack():

private static Func<TModel, TValue> GetFuncFastTrack(Expression<Func<TModel, TValue>> lambdaExpression) { 
    ParameterExpression modelParameter = lambdaExpression.Parameters[0]; 
    Expression body = lambdaExpression.Body; 

    return FastTrack<TModel, TValue>.GetFunc(modelParameter, body); 
}

The original expression has been split into its single parameter (our model) and its body and pased to the FastTrack class.

FastTrack<TModel, TValue>.GetFunc method

And finally here’s the relevant portion of the FastTrack<TModel, TValue>.GetFunc() method.

public static Func GetFunc(ParameterExpression modelParameter, Expression body) { 
    ... 
    ... 
    ... 
    { 
        MemberExpression memberExpression = body as MemberExpression; 
        if (memberExpression != null) { 
            ... 
            ... 
            ... 
            else if (memberExpression.Expression == modelParameter) { 
                // model => model.Member 
                return GetModelMemberLookupFunc(memberExpression.Member, false /* isStatic */); 
            } 
            ... 
            ... 
            ... 
        } 
    } 
    ... 
    ... 
    ... 
}

As you can see the expression body has been successfully cast to a MemberExpression. 

A MemberExpression has two public properties:

  • Expression – which represents the containing object (our "model")
  • Member – which is the MemberInfo instance representing the access (our "ProductName")

MVC compares the Expression property to the ParameterExpression.  They are equal so it calls:

GetModelMemberLookupFunc(memberExpression.Member, false /* isStatic */);

which is just a wrapper for this:

return _modelMemberLookupCache.GetFunc(member, isStatic);

I sense that we’re getting close to a cache…

ModelMemberLookupCache

This _modelMemberLookupCache is a static member of type ModelMemberLookupCache.  ModelMemberLookupCache is derived from an abstract base class called ReaderWriteCache<TKey, TValue>.  It provides a creation function for the case when the cache lookup fails i.e. the first time.  Here’s the creation function:

private static Func<TModel, TValue> CreateFunc(MemberInfo member, bool isStatic) { 
    ParameterExpression modelParam = Expression.Parameter(typeof(TModel), "model"); 
    MemberExpression memberExpr = Expression.MakeMemberAccess((!isStatic) ? modelParam : null, member); 
    Expression<Func<TModel, TValue>> lambda = Expression.Lambda<Func<TModel, TValue>>(memberExpr, modelParam); 
    return lambda.Compile(); 
}

In effect it recreates our original expression but "standardises" it by replacing the name of the parameter with "model".  This is then compiled into a delegate and stored in the cache with the MemberInfo instance as the key.

So the next time ASP.NET MVC encounters:

model => model.ProductName

it will be able to return a pre-compiled delegate from the cache – a significant boost to performance.

Next I’ll look at the other cases FastTrack caters for, and dig around a bit more in ReaderWriterCache<TKey, TValue>.

Digging around: TextBoxFor in ASP.NET MVC 2

This is a companion post to Scott Guthrie’s ASP.NET MVC 2: Strongly Typed Html Helpers.

I was interested in what made this code:

<%= Html.TextBoxFor(model => model.ProductName) %>

in an aspx view template produce this html:

<input id="ProductName" name="ProductName" type="text" value="Aniseed Syrup" />

In order to do it ASP.NET MVC has performed two distinct operations:

  1. parsed the expression tree produced by the compiler for model => model.ProductName to extract the name of the property ("ProductName") to use in the id and name attributes of the input element
  2. compiled the expression and invoked the resulting delegate to produce the "Aniseed Syrup" value

TextBoxFor extension method

The call to Html.TextBoxFor ends up in the following extension method in the InputExtensions class:

public static MvcHtmlString TextBoxFor<TModel, TProperty>( 
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expression, 
    IDictionary<string, object> htmlAttributes) 
{ 
    return TextBoxHelper( 
        htmlHelper, 
        ModelMetadata.FromLambdaExpression(
            expression, 
            htmlHelper.ViewData).Model, 
        ExpressionHelper.GetExpressionText(expression), 
        htmlAttributes); 
}

I’ve highlighted the second and third parameters. The call to TextBoxHelper() does the final rendering by:

  • calling Convert.ToString() on the second parameter to populate the value attribute of the input element
  • using the third parameter to populate the name and id attributes of the input element

But let’s backtrack a bit first and look at the TextBoxFor signature itself.

Quick detour to Expression<Func<TModel, TProperty>>

Here’s the signature of the TextBoxFor method in the previous section:

public static MvcHtmlString TextBoxFor<TModel, TProperty>( 
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expression, 
    IDictionary<string, object> htmlAttributes) 
{ 
... 
... 
} 

By declaring a parameter of type Expression<Func<TModel, TProperty>> the TextBoxFor method has asked the compiler to generate an expression tree rather than a delegate.

Expression<TDelegate> is derived from LambdaExpression, which represents an expression tree which can be compiled into a delegate by calling its Compile() method.

Interestingly, the implementation of Compile() in Expression<TDelegate> calls Compile() on its base and casts the resulting delegate to TDelegate, so its a pretty thin wrapper for LambdaExpression.

All these uses of the term "lambda expression" can be mighty confusing. We call

model => model.ProductName

a lambda expression when we see it in code. The compiler however will treat it as an anonymous function or an expression tree, depending on the context

If it’s being assigned to Func<TModel, TProperty> it is treated as an anonymous function.

But if it’s being assigned to Expression<Func<TModel, TProperty>> then it is treated as an expression tree.

Anyway, back to the TextBoxFor method.

ExpressionHelper.GetExpressionText

public static MvcHtmlString TextBoxFor<TModel, TProperty>( 
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expression, 
    IDictionary<string, object> htmlAttributes) 
{ 
    return TextBoxHelper( 
        htmlHelper, 
        ModelMetadata.FromLambdaExpression(
            expression, 
            htmlHelper.ViewData).Model, 
        ExpressionHelper.GetExpressionText(expression), 
        htmlAttributes); 
} 

We want to get the text with which to populate the id and name attributes of our text box.

Because MVC has an expression tree rather than a delegate it can can pick it apart to find out, in this case, the name of the property being accessed.

Here’s my stripped down version of the implementation of GetExpressionText(), which covers the case of our simple model.ProductName property access:

public static string GetExpressionText(LambdaExpression expression) 
{ 
    MemberExpression memberExpression = (MemberExpression)expression.Body; 
    return memberExpression.Member.Name; 
}

The body of the expression is cast to a MemberExpression so that its Member.Name property can be accessed.

This returns "ProductName".

That was easy. Now on to the evaluation of the expression itself.

ModelMetadata.FromLambdaExpression

public static MvcHtmlString TextBoxFor<TModel, TProperty>( 
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expression, 
    IDictionary<string, object> htmlAttributes) 
{ 
    return TextBoxHelper( 
        htmlHelper, 
        ModelMetadata.FromLambdaExpression( 
            expression, 
            htmlHelper.ViewData).Model, 
        ExpressionHelper.GetExpressionText(expression), 
        htmlAttributes); 
} 

OK so we’ve got hold of of the string

Creating a Windows Domain in the Cloud

I recently had to create a Windows Domain in the Cloud, hosted by Amazon Web Services. It posed a particular set of issues.

We created a Windows Server 2003 domain controller instance, and installed DNS on it as well. We assigned the domain controller an elastic IP, so that its public IP address and name would not change (more on this later).

For each server instance wanting to join the domain:

  • we disabled the AWS “auto-naming” setting in AWS configuration
  • we set its primary name server to be the domain controller, using the DC’s public elastic IP address
  • we could then join the domain successfully

But there were drawbacks to this approach:

  1. We didn’t want to use the public (permanent) IP address of the domain controller – it meant we had to have crazily loose security group settings, and the Amazon bills were higher
  2. Because we had overriden the primary name server for each of the server instances, they could no longer resolve Amazon public instance names to private IP addresses. In order to work this “magic” you need to be able to find Amazon’s own DNS

We solved problem 2 by using DNS forwarding on the domain controller – forwarding to Amazon’s own name server. This meant that, for example, the public name of our domain controller resolved to a private IP address.

We solved problem 1 by using the private IP address of the domain controller as the name server for the server instances in the domain.

But what if the DC fails? Doesn’t it get a new private IP address when we recreate it? Won’t we then have to change this setting for all the servers?

Our solution was to add the Amazon DNS server as the secondary name server for each of the server instances. We then wrote a Windows Service that did the following:

  • performed a lookup of the public name of the DC
  • if the private IP address returned was different to that of the primary name server, updated the entry for the primary name server

Our reasoning was: if the DC fails and has to be recreated, the lookup will still succeed using the secondary (Amazon’s) name server.

Phew.

Obtaining MSI Product Version with Powershell 1.0

Want to know what version of a product is in an MSI? You need the ProductVersion property.

It’s a bit tricky to get at from Powershell 1.0, because there’s no runtime type info for the Installer class.

The following isn’t pretty, but it does the job.

#
# Fetches ProductVersion from MSI file
#
param($msiPath)
if($msiPath -eq $null)
{
"Expects full path to MSI file"
return;
}

# Create Installer instance
$installer = New-Object -comObject WindowsInstaller.Installer

# Call Installer.OpenDatabase(name, openMode)
$database = $installer.GetType().InvokeMember("OpenDatabase", [System.Reflection.BindingFlags]::InvokeMethod, $null, $installer, ($msiPath, 0))

# Call Database.OpenView(sql)
$view = $database.GetType().InvokeMember("OpenView", [System.Reflection.BindingFlags]::InvokeMethod, $null, $database, "SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'")

# Call View.Execute()
$view.GetType().InvokeMember("Execute", [System.Reflection.BindingFlags]::InvokeMethod, $null, $view, $null)

# Call View.Fetch()
$record = $view.GetType().InvokeMember("Fetch", [System.Reflection.BindingFlags]::InvokeMethod, $null, $view, $null)

# Get Record.StringData(field)
$productVersion = $record.GetType().InvokeMember("StringData", [System.Reflection.BindingFlags]::GetProperty, $null, $record, 1)

Write-Host $productVersion