Sunday, September 18, 2011

You, me and WinRT

I went to Tech.Ed Au for the first time this year and I learnt a bit, but mostly I got two things from it. A red, flashy, bouncy ball and a silver usb race car. Now I just want you to concentrate on the red, flashy, bouncy ball.. You're still thinking the race car, aren't you? And this was the problem for me with //build/

What we have here is a failure to communicate.

So, for me, the slide that everybody points to is the techno stack, the green side and the off colour blue side. But we were only supposed to concentrate on the green side. And now we have a problem, we are hypothesizing about that off colour blue side, why is it an off colour, is it dying?


If you look at WinRT, you saw a pretty slick looking tablet interface. Tablet?! This is windows 8, the future.. Yes, dex, for some of us, it is. Downloading the dev preview you quickly notice, that with a mouse, this is probably not going to be rainbows and unicorns - even with a gesture mouse.

So, nothing is dying, this is just an attempt to show people WinRT and that's why the tablet stuff is glued to the start button, not saying that it wont on tablets, but in a previous post, some guy said, the metro interface will be downloadable, just like any app.

For me the techno stack slide should have been just the green side, and it would have, if it wasn't for, the gangs of .net.

These are the guys who attended the event looking for blood, looking for, traces of dead stuff. If you really look hard, nothing is dead, or dying, its a pretty happy tablet world, where everybody is on equal footing, even web guys and c++'ers. But blood was found, because of the push for the green side. Does that mean I am dead, they replied, .net, every other way to do things?

Look, I know vampires are pretty popular at the moment, and dead things, and blood is cool, but I want you to know, windows is better than that. Now go play with this red flashy ball for the rest of this post, fetch..

The biggest hint at the new world in the dev preview, is that c++ is in on the party, it too, is on equal footing and has the Xaml interface. Think about this for a second why, this language, the performance maestro. Why is he here in WinRT? Well its a preview, I think, a way to show that you'll be able to build any type of executable, using the new, core, Xaml interface, metro or otherwise.
Now go download the developer preview and play with WinRT, learn it, love it. Because you'll be able to use the same Xaml stuff outside of metro, as the new interface builder for windows. (I, think)

One more thing, if you read another post about this subject, take some garlic with you, because vampires suck.

Peace out..

Saturday, May 28, 2011

Windows phone Linq to SQL: First blood

Windows phone mango introduces SQL CE database support through Linq to SQL. In my last post I called this Linq to SQL phone ORM: MiniLinq.
MiniLinq does not support the DBML mapping file, you add the attributes to your DTOs by hand, the database is created based on your model when the app is loaded.

   1:  using (MangoDb mangoDb = new MangoDb())
   2:  {
   3:      if (!mangoDb.DatabaseExists())
   4:      {
   5:          mangoDb.CreateDatabase();
   6:      }
   7:  }

In seven lines of code the initial schema of the MangoDb Data Context is created. When you update the model, add new Properties or Entities, you have to call into the new DatabaseSchemaUpdater api introduced especially for the phone. This can be created through an extension method on DataContext and can be used by importing the namespace Microsoft.Phone.Data.Linq.

   1:  DatabaseSchemaUpdater updater = mangoDb.CreateDatabaseSchemaUpdater();



This class provides a property and five methods. Typically a database is updated more than once in an applications lifetime. We use the DatabaseSchemaVersion for this purpose to infer what has been included in the database before and only add what is not there. Adding an object that already exists will throw a SqlCeException when the Execute method is called on database schema updater. The Execute method commits a batch update operation, this allows everything to be completed in a transaction and protects the database from being left in an indeterminate state if an error occurs.

   1:  int version = updater.DatabaseSchemaVersion;
   2:   
   3:  updater.AddTable<T>();
   4:  updater.AddColumn<T>("columnPropertyName");
   5:  updater.AddIndex<T>("indexName");
   6:  updater.AddAssociation<T>("associationPropertyName");
   7:   
   8:  updater.Execute();



All four add methods take a generic, which is the model you are updating. This means the updater will read the meta data of the Mapping attributes on you model, keeping the method for creating, reading and updating the database exactly the same.

Databases are not kept on a server somewhere, they are stored in Isolated Storage on the users phone and this means you have many databases to look after. This brings with it an interesting conceptual problem when trying to update the database. The problem is due to the DatabaseSchemaVersion property, because this property is initialised when the database is first created to 0 and there is no user override.

I will discuss the problem with a tale of three versions and two users. You release the first version of your application. Bob decides to download your new data driven application and runs the application this creates the database with a version 0.

image

You make changes to your app and release v2 to the marketplace. Bob updates his app and the Db is now version 1. Also, a new user Panda downloads the app at this time this creates version 0 on her device.

image

You makes changes again for version 3 of your app. Both Bob and Panda update, Bobs update sails through, you are using logic like this:

   1:  using (MangoDb mangoDb = new MangoDb())
   2:  {
   3:      if (mangoDb.DatabaseExists())
   4:      {
   5:          DatabaseSchemaUpdater updater = mangoDb.CreateDatabaseSchemaUpdater();
   6:         
   7:          int version = updater.DatabaseSchemaVersion;
   8:   
   9:          if (version < 1)
  10:          {
  11:              UpdateDatabaseForAppVersion2();
  12:          }
  13:   
  14:          if (version < 2)
  15:          {
  16:              UpdateDatabaseForAppVersion3();
  17:          }
  18:   
  19:          updater.Execute();      
  20:      }
  21:      else
  22:      {
  23:          mangoDb.CreateDatabase();
  24:      }
  25:  }


However Panda’s update does not bode so well, The application fails to start when a hidden SqlCeException is thrown, because because the logic will try to update Panda’s application as a version 1 application, because the database is version 0. However, Panda initially installed the app at version 2. This makes Panda very sad..

You can resolve this by not using the DatabaseSchemaVersion at all. Use an application version number instead to upgrade your database.

This is not the only problem I have with database updates. The second problem is the upgrade occurs when the user launches the application, not when the application is installed/updated. This, to me, is a poor user experience and can lead to slow start times, more than the magic 10seconds, maybe!

To resolve this, Microsoft can you please allow an UpdateTask class in the Windows phone api? This will allow database upgrades and other local storage related operations to run when the user is installing the application, not when the application launches.

You saw in this post how to use the DatabaseSchemaUpdater and some of the issues around this new api in Windows phone. The SDK is still beta, so I expect the DatabaseSchemaVersion property will be dropped in a refresh of the tools and hopefully we can have a mechanism to run operations when the user is installing/updating an application to lead to better user experiences.

Wednesday, May 25, 2011

Windows phone: Mango DB

Did you know the Windows Phone Developer Tools 7.1 Beta is out? Wow, what a mouthful and very, very exciting.

One of the new features to be supported when Mango is released, is a database. Databases are common place in other mobile devices, but this was a missing feature from the original release of Windows phone 7, but now it’s here, in mango. let’s run down what you need to do to get the minimum database up and running.

The DataContext code

   1:  using System.Data.Linq;
   2:  using Mango1.Models;
   3:   
   4:  namespace Mango1.Data
   5:  {
   6:      public class MangoDb : DataContext
   7:      {
   8:          public MangoDb()
   9:              : base("Data Source=isostore:/MangoDb.sdf") { }
  10:   
  11:          public Table<SuperJuicy> SuperJuicy;
  12:         
  13:      }
  14:  }

As you see mango supports none other than (a lighter) LinqToSql. This is a refreshing return but we’re old friends and if your not, I think you’ll like him. We shall call him MiniLinq

In order to interact with the database You need to inherit from System.Data.Linq.DataContext and provide a default constructor that passes in the connection string. You can complicate the hell out of this, if you want, but this is all you’ll need to do.

This connection string is really simple, at a minimum you only need to supply the standard SQL “Data Source” property, but it’s value is completely different, it has isostore:/ at  the front of the database file name.

You can have two different kinds of databases in Mango:
  1. Read only databases deployed inside your application; 
  2. Read/Write databases stored in Isolated Storage.
isostore:/ means we are creating a Read/Write database in Isolated Storage.

The next step in the process is to create your parent entities, called aggregate roots. In this example we are defining a public field called SuperJuicy of type Table<SuperJuicy>. This, believe it or not, is auto-populated by MiniLinq at runtime, when you create the DataContext. Also, this is OK too, in a real implementation the MangoDb will be wrapped by the Repository pattern.

The ORM

   1:  [Table(Name="SuperJuicy")]
   2:  public class SuperJuicy
   3:  {
   4:      int juicyId;
   5:   
   6:      [Column(Name = "JuicyId",          
   7:          IsPrimaryKey = true,           
   8:          IsDbGenerated = true,          
   9:          DbType = "int IDENTITY(1,1)",  
  10:          AutoSync = AutoSync.OnInsert,          
  11:          CanBeNull = false,             
  12:          Storage = "juicyId"            
  13:          )]
  14:      public int JuicyId { get { return juicyId; } }
  15:   
  16:      [Column(Name = "JuicyRating",
  17:          CanBeNull = false,
  18:          DbType="int"
  19:          )]
  20:      public int JuicyRating { get; set; }
  21:  }

Mapping objects to your relational schema is really nice, there is no DBML, so you’ll have to type those attributes out by hand (maybe SQLMetal can, but this is the world of code-first man, get your hands dirty)

Give your table a name by adorning the Table attribute to your class. My table will be named SuperJuicy. At the very minimum you need one property on your class when the column is not Db Generated and two, if you have a Db Generated column.

Let’s walk through the specification of the JuicyId property:
  • I am a read only property named JuicyId
  • My column Name will be called JuicyId
  • My database type is integer and will be an Identity seed 1, increment 1.
  • I am a Primary Key
  • The database will create my values
  • The database will synchronise this value when I am first inserted.
  • I cannot be null
  • Because I am read only, my backing field is juicyId (VB.net _juicyId)

Too easy? This is easier, the JuicyRating property:
  • I am a read/write property name JuicyRating
  • My column name will be called JuicyRating
  • My database type is integer
  • I cannot be null
Now we have a mapped class, lets use it. For this example, we can just do this where ever you want:  

   1:  using (MangoDb mangoDb = new MangoDb())
   2:  {
   3:      if (!mangoDb.DatabaseExists()) 
   4:      {
   5:          mangoDb.CreateDatabase();
   6:      }
   7:   
   8:      SuperJuicy mango = new SuperJuicy { JuicyRating = 180 };
   9:   
  10:      mangoDb.SuperJuicy.InsertOnSubmit(mango); 
  11:      mangoDb.SubmitChanges();
  12:   
  13:      int id = mango.JuicyId;//Will be 1 :)
  14:  }
The important things in this code is we create the MangoDb, check to see if the database exists, if not create it.

InsertOnSubmit does not insert straight away you can record a whole heap of steps before calling SubmitChanges and this will happen in a batch. This is currently, the recommended approach.

MiniLinq is a light weight LinqToSQL and is provided in Windows phone Mango. This is just touching the surface and we’ll talk about database schema syncing tomorrow. There will be blood, sweat and tears on this, I promise.

Tuesday, May 24, 2011

Windows phone: Mango

Perhaps an overreaction, but did you watch what I did last night: The Mango public announcement.

This was performed by two guys in a cramped space continually handing over the same phone and what it appears to be rushing through the presentation. To me a cramped space means this is not really that important. Further, the rushing means, I have work to be done that is not complete and I really hope you like what has been done so far. Not really all that inspiring for the first time the media see the “new direction” of windows phone and a chance to sway people into buying a phone before the mango release.

This pales in comparison to the ipad 2 announcement, this was a product (in defence, was largely completed) but: This was Steve Jobs and friends hanging out together, sitting in chairs, showing a product and the lifestyle, calm, relaxed, that the ipad 2 will bring to you. This was also performed in a large space with people joining the floor from multiple entry points, creating an expectation of “what’s going to happen next”

At the end of the ipad2 presentation was: I want one. At the end of the windows phone presentation: Oh well, let’s see what happens in September.

Why did I tell you this? Well, this just leaded to my post. I wanted to see what my company thought of Mango (I was hoping for inspiration that was missing from last night) and the first reply was:

“I don’t see anything that exciting about Mango. Am I missing something? It just looks like they’ve finally delivered on the features that should’ve been in v1.”

This echoes the same feelings that I have about the platform. Well played Microsoft, well played.

Finally in saying that, I believe Microsoft is on the correct path with Windows phone. The phone is a personal device that knows where you are, and who you are. This will lead to compelling augmented reality experiences and we saw some of this last night. I just hope they don’t kill the platform that should deliver these experiences.

PS: I have no qualification for talking about body language and psychology, it’s an observation only.

Wednesday, February 9, 2011

WebMatrix, the oldschool is back and sharp as Razor

I remember the days, back in the land of vb script, writing web pages was fun! I thought the closest I was going to get to these "good" old days, using ASP.net, was MVC. But wait, there's WebMatrix! This piece of tech allows you to get even closer to the wonder years and write SQL code in line with your HTML..

OK I have let you mull over that for a while.. Let's move on.

I have written a simple helper file that allows you to abstract this code into a different file in the App_Code folder so your cshtml file can be light-weight again.

Check out the sample app today: WebMatrix helpers

Monday, August 9, 2010

I have been told I just need one line to start

I am a software developer in the ever changing world of the .NET framework. The aim of this blog will be to share my experiences and maybe cop some criticism along the way.

Lets see how this pans out.