CHAPTER 8 ■ SQL AZURE 293 else if (null != this. parentForm) { this. parentForm.DisplayMessage( string.Format("Can not find the parameter <{0}>", txtParameter.Text), true ); } } private void radioButtonQuery CheckedChanged(object sender, EventArgs e) { this.groupParameter.Enabled = false; } private void radioButtonStoredProcedure CheckedChanged(object sender, EventArgs e) { this.groupParameter.Enabled = true; } private void richTextBoxCommandText MouseUp(object sender, MouseEventArgs e) { if (null != eventSelectedTextChanged) { try { eventSelectedTextChanged( this, new SelectedTextArgs(String.IsNullOrEmpty(SelectedText)?null:this) ); } catch { } } } void richTextBoxCommandText PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) { if (null != eventBubblePreviewKeyDown) { eventBubblePreviewKeyDown(this, e); } } private void SQLDataServiceControl Leave(object sender, EventArgs e) { this.richTextBoxCommandText.Clear(); this.richTextBoxCommandText.Text = sqlDatabaseAccessService.Command.Text; richTextBoxCommandText MouseUp(this, null); } } } CHAPTER 8 ■ SQL AZURE 294 FormSQLAzureConnect The main window of SQLAzureConnect also has a binding source object defined to bind the data source to the data object instance’s XML SQLDatabaseAccessRoot as Figure 8-25 shows. Figure 8-25. A BindingSource of the FormSQLAzureConnect is defined to bind the data source to the data object instance’s XML SQLDatabaseAccessRoot When an XML data file is loaded, the data will be deserialized into a data object and assigned to the member variable sqlDataAccessRoot, and a member method UpdateUI() is called. This method loops through all the predefined services, factors out the SQLDataServiceControls, and calls the AddPage() method to assign each control to a tab page. Each SQLDatabaseControl has an underlying ParameterControl if the SQL command type is a stored procedure and requires parameters as Listing 8-12 shows. When a tab page has been created, it registers two events from the underlying SQLDataAccessControls, eventSelectedTextChanged and eventBubblePreviewKeyDown, triggered when the script text is selected by the user, and the F5 shortcut key is pressed to invoke the SQL script. These two events have been handled in two anonymous methods. These two anonymous methods are implemented in the method AddPage() and shown in Listing 8-17. Listing 8-17. The Main Form Formsqlazureconnect Uses the Data Objects Deserialized from an XML Data File to Factor Out the UI Tab Pages and Underline SQLServiceControls private void UpdateUI() { if (null != sqlDataAccessRoot) { this.txtServer.Text = sqlDataAccessRoot.ServerConnection.ServerName; this.txtDatabase.Text = sqlDataAccessRoot.ServerConnection.Database; this.txtUserID.Text = sqlDataAccessRoot.ServerConnection.Login; this.txtPassword.Text = sqlDataAccessRoot.ServerConnection.Password; for (int i = 0; i < sqlDataAccessRoot.SqlDataService.Length; ++i) CHAPTER 8 ■ SQL AZURE 295 { this. AddPage( sqlDataAccessRoot.SqlDataService[i].Subject, ref sqlDataAccessRoot.SqlDataService[i]); } this.tabControlServices.SelectedIndex = 0; } } private TabPage AddPage(string pageKey, ref SQLDatabaseAccessRootSqlDataService sqlDatabaseAccessRoot) { TabPage page = null; if (IsPageExisted(pageKey, this.tabControlServices)) { DisplayMessage( string.Format("The name <{0}> of service already exists", pageKey), true ); return null; } page = new TabPage(pageKey); page.ForeColor = Color.Navy; SQLDataServiceControl serviceCotnrol = new SQLDataServiceControl(ref sqlDatabaseAccessRoot, this); serviceCotnrol.eventSelectedTextChanged += (s, e) => { this.btnExecute.Text = null == (e as SelectedTextArgs).ServiceControl? "&Execute" : "&Execute Select"; this.btnExecute.BackColor = null == (e as SelectedTextArgs).ServiceControl ? Color.WhiteSmoke : Color.Goldenrod; this. TextSelected = null == (e as SelectedTextArgs).ServiceControl ? null : ((e as SelectedTextArgs).ServiceControl as SQLDataServiceControl).SelectedText; }; serviceCotnrol.eventBubblePreviewKeyDown += (s, e) => { if (e.KeyCode == Keys.F5) { this.btnExecute Click(this, null); } }; page.Controls.Add(serviceCotnrol); serviceCotnrol.Dock = DockStyle.Fill; this.tabControlServices.TabPages.Add(page); this.tabControlServices.SelectedTab = page; return page; } CHAPTER 8 ■ SQL AZURE 296 SQLAzureConnect also allows the user to create a new service and underlying parameters manually and edit or delete existing services. The data can be saved and played back. The rest of the implementation for the UI is fairly straightforward, and the total number of code lines is just around 300, thanks to the XML data-driven dynamic factory approach. You can download the source code from the bundled project ZIP file. Feel free to use it directly or to add more functions. Summary In this chapter I covered the newly minted SQL Azure features that replaced SQL Data Services. SQL Azure is an exciting innovation, as it is the first relational model cloud database, and it has many advantages. One of the main advantages is that it provides a familiar environment for most developers, which means existing applications can easily be migrated from existing databases. During the course of this chapter I took you through the fundamentals of SQL Azure to show you its basic features. We created tables, inserted data, and queried the database using SQL Server Management Studio. The main example in the chapter is a tool for working with SQL Azure, and on-premises SQL Server installations, which allows you to unify all your relational database testing and debugging. C H A P T E R 9 ■ ■ ■ 297 Deploy Applications and Production Maintenance In this chapter I am going to provide examples of how to deploy Azure Storage and applications to the cloud. The process of deployment is fairly straightforward and intuitive. The steps are as follows, each of which I’ll touch on in this chapter: 1. Prepare the application package and configuration package for deployment. 2. Deploy table storage. 3. Deploy the cloud application. I’ll also cover the maintenance of a deployed cloud application. Preparing the Application Package and Configuration Package for Deployment The application and associated configuration need to be packed up before they can be deployed to the cloud. These packages can be generated from Visual Studio as Figure 9-1 shows. This example can be found in Exercise 4-3 from the download. Select Publish from the context menu by right-clicking on the cloud application solution’s node in Solution Explorer.