Quite a number of times, I have been asked how hard it actually is to move an existing ASP.NET+SQL Server application over to Windows Azure. My response to this is generally the a classic "it depends" - provided there are no major pitfalls in the application architecture, it is a straight-forward exercise to perform this transition.
So, the first thing to do was to create a sample application that includes some interaction with an “on-premise” database. The database, I got from here: http://msftdbprodsamples.codeplex.com/releases/view/55926 – just your stock-standard AdventureWorks database.
Now for the application itself. I decided to go for a simple data-grid showing the customer data from above database. So I went to Visual Studio and created a new ASP.NET web project:
Then, I added a GridView control to the Default.aspx page, specifying the Customers table and selecting some data from there.
Code-wise, this ends up like this in the ASPX page:
1: <asp:GridView ID="GridView1" runat="server" CellPadding="4"
2: DataSourceID="AdvWorks" ForeColor="#333333" GridLines="None"
3: AutoGenerateColumns="False" DataKeyNames="CustomerID">
4: <AlternatingRowStyle BackColor="White" ForeColor="#284775" />
6: <asp:BoundField DataField="CustomerID" HeaderText="CustomerID"
7: InsertVisible="False" ReadOnly="True" SortExpression="CustomerID" />
8: <asp:BoundField DataField="CompanyName" HeaderText="CompanyName"
9: SortExpression="CompanyName" />
10: <asp:BoundField DataField="Title" HeaderText="Title" SortExpression="Title" />
11: <asp:BoundField DataField="FirstName" HeaderText="FirstName"
12: SortExpression="FirstName" />
13: <asp:BoundField DataField="MiddleName" HeaderText="MiddleName"
14: SortExpression="MiddleName" />
15: <asp:BoundField DataField="LastName" HeaderText="LastName"
16: SortExpression="LastName" />
17: <asp:BoundField DataField="EmailAddress" HeaderText="EmailAddress"
18: SortExpression="EmailAddress" />
20: <EditRowStyle BackColor="#999999" />
21: <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
22: <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
23: <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />
24: <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />
25: <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
26: <SortedAscendingCellStyle BackColor="#E9E7E2" />
27: <SortedAscendingHeaderStyle BackColor="#506C8C" />
28: <SortedDescendingCellStyle BackColor="#FFFDF8" />
29: <SortedDescendingHeaderStyle BackColor="#6F8DAE" />
31: <asp:SqlDataSource ID="AdvWorks" runat="server"
32: ConnectionString="<%$ ConnectionStrings:AdvWorksConnectionString %>"
33: SelectCommand="SELECT [CustomerID], [CompanyName], [Title], [FirstName], [MiddleName], [LastName], [EmailAddress] FROM [SalesLT].[Customer]">
35: <asp:SqlDataSource ID="SqlDataSource1" runat="server"></asp:SqlDataSource>
2: <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
3: providerName="System.Data.SqlClient" />
4: <add name="AdvWorksConnectionString"
5: connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=AdventureWorksLT2008R2;Integrated Security=True"
6: providerName="System.Data.SqlClient" />
Hitting <F5> verifies that this actually works as expected.
When moving a data-driven application to Windows Azure, I generally recommend doing this in two steps – one for the Database and the other for the application itself. That way, you can more easily identify where a potential problem lies. If you move it all up in one go, it will be hard to discern between application-related and data-related issues.
While it is theoretically possible to move the application first, it is a lot easier to begin with the database, as it is very easy to access SQL Azure from an on-premise IIS, but accessing an on-premise SQL Server from a Windows Azure application involves some extra plumbing.
For the database migration, I use the SQL Azure Migration Wizard from codeplex (http://sqlazuremw.codeplex.com/). This will adjust the schema to a SQL Azure-friendly form and alert me to any issues that may occur in the process.
The Wizard actually did come up with a few errors and warnings, like:
XML Schema Collections are currently not supported in SQL Azure
The following XML Schema Collections were found:
None of the errors or warnings are critical to my project, so I went ahead and allowed the Wizard to create me a new database called “AdvWorks” in my SQL Azure subscription.
In a real-life scenario, of course, the impact of the errors and warnings would need to be properly evaluated and might involve some code change in the application to circumvent.
In order to demonstrate that switching the database actually does anything, I then pulled up SQL Server Management Studio to slightly modify the data on the SQL Azure side:
1: UPDATE [AdvWorks].[SalesLT].[Customer]
2: SET [MiddleName] = 'AZURE'
Every Customer on the Azure side will now show up with a Middle Name of “AZURE”.
So the only thing that remained to be done is to change the connection string in my web.config:
1: <add name="AdvWorksConnectionString"
2: connectionString="Server=tcp:[SERVER].database.windows.net,1433;Database=AdvWorks;User ID=[USER]@[SERVER];Password=[PASSWORD];Trusted_Connection=False;Encrypt=True;"
3: providerName="System.Data.SqlClient" />
(change [SERVER], [USER] and [PASSWORD] to whatever is applicable on your SQL Azure server)
Running this showed exactly what I would have hoped for – everyone now goes for a fancy new middle name:
For this, I simply added a new Windows Azure Cloud project to my solution:
in the next screen, I simply pressed “Next” as I didn’t need any additional Azure roles.
The Azure project automatically became the new StartUp project and I could right-click the “Roles” node in that project and select “Web Role Project in Solution…”, which brought up this dialog:
Adding this created the required wiring for a standard HTTP port and needed no additional tweaking. Hitting <F5> again ran the same project, but now inside the Windows Azure Compute Emulator on my machine:
Apart from the URL, no difference to the previous step and that’s exactly what we want.
Now, all that was needed was to deploy this to Windows Azure. This yielded exactly the same result, just delivered directly from our Cloud Servers.
What remains to be done are things like:
Yes, I know – oversimplification on that last item, but the point is made – the core part of moving a data-driven ASP.NET application to Windows Azure is no real issue in itself and can happen quite rapidly. The devil may be in the detail, but there is no rocket science involved in the groundwork.