Введение в облачные решения Microsoft

Работа с Windows Azure Table

Показывать лекцию целиком

В качестве примера рассмотрим простое приложение - справочник контактов, с поддержкой функции добавления, изменения и удаления.

Прежде всего создадим проект "AzureTableExample", необходимый для данной лабораторной работы.

(рис 17.1)

Для демонстраци возможностей приложения, использующего в качестве хранилища данных WindowsAzure Table нам понадобится только веб - роль, добавьте ее решению.

В свойствах веб - роли определим строку подключения к эмулятору хранилища Azure.

(рис 17.2)

Создание классов будущего приложения

Класс - Контакт.

Добавим следующие ссылки:

using Microsoft.WindowsAzure.StorageClient;

Контакт будет содержать следующую информацию:

  • Имя
  • Фамилию
  • Контактный телефон
  • Адрес электронной почты
  • Добавим C# класс нашей рабочей роли - Contact.cs и зададим необходимые свойства, унаследовав его от Microsoft.WindowsAzure.StorageClient.TableServiceEntity :

    class Contact : Microsoft.WindowsAzure.StorageClient.TableServiceEntity
        {
    
        }

    Определим требуемые свойства для класса контактов. И в конечном итоге, наш класс будет выглядеть следующим образом:

    class Contact : Microsoft.WindowsAzure.StorageClient.TableServiceEntity
        {
            public String FirstName { get; set; }
            public String LastName { get; set; }
            public String TelNumber { get; set; }
            public String Email { get; set; }
        }

    Класс - контекст для доступа ContactContext.cs

    Нам понадобятся следующие ссылки:

    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.StorageClient;
    using System.Data.Services.Client;

    Создадим соответствующий C# - класс, унаследуем его от TableServiceContext и определим конструктор:

    class ContactContext : TableServiceContext
        {
            public ContactContext (Uri baseAddress, StorageCredentials credentials): base(baseAddress.AbsoluteUri, credentials) {}
        }

    Добавим свойство для возвращения data service - запроса для таблицы Contacts.

    public IQueryable<Contact> ContactData
            {
                get
                    {
                       return this.CreateQuery<Contact>("Contacts"); 
    
                    }
             }

    Последним шагом по созданию класса - контекста является создание метода для добавления строки в таблицу. В итоге, класс должен выглядеть следующим образом 5.1:

    class ContactContext : TableServiceContext
        { 
            
          public IQueryable<Contact> ContactData
            {
                get
                    {
                       return this.CreateQuery<Contact>("Contacts"); 
    
                    }
             }
    
            public ContactContext (Uri baseAddress, StorageCredentials credentials): base(baseAddress.AbsoluteUri, credentials) {}
    
            public void Add(Contact cntct) 
            {
      
                this.AddObject("Contacts", cntct);
      
                this.SaveChanges();
      
             }
    
    
        }

    Интерфейc

    Создадим веб - форму для работы с нашим контакт - листом.

    Внешний вид веб формы

    (рис 17.3)

    Задача 1. Добавление данных в таблицу

    В обозревателе решений найдите файл Global.asax.cs. В метод Application_Start необходимо добавить код создания таблицы, в случае если она не была создана до этого:

    void Application_Start(object sender, EventArgs e)
            {
    
                CloudStorageAccount.SetConfigurationSettingPublisher(
                    (configName, configSettingPublisher) =>
                    {
                        var connectionString =
                            RoleEnvironment.GetConfigurationSettingValue(configName);
                        configSettingPublisher(connectionString);
                    }
                ); 
    
                var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
    
    //создание таблицы Windows Azure Table
                CloudTableClient _tc = null;
                _tc = account.CreateCloudTableClient();
                _tc.CreateTableIfNotExist("Contacts");
    
            }

    Далее в обработчике события нажатия кнопки "AddContact" необходимо создать аккаунт для подключения к хранилищу, используя параметр строки подключения "DataConnection String" . После этого, для непосредственного добавления данных в таблицу нам понадобится экземпляр класса - контекса. Вызвав метод "Add" данного класса (листинг 17.1) мы добавим строку в таблицу, передав в качестве параметра экземпляр класса "Contact" . Обратите внимание, в классе Contact мы не описывали необходимые параметры для добавления строки в таблицу (ключ секции и ключ строки), класс унаследовал их от родителя. В качестве значения ключа секции зададим произвольную строку, в качестве ключа строки будем использовать сочетание "Last Name + First Name" .

    protected void btn_add_Click(object sender, EventArgs e)
            {
                var statusMessage = String.Empty;
                try
                {
                    var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
                    var context = new ContactContext(account.TableEndpoint, account.Credentials);
    
                    context.Add(new Contact { PartitionKey = "MyContacts", 
                          RowKey = this.tb_lastname.Text + " " + this.tb_firstname.Text, 
                             FirstName = tb_firstname.Text, LastName = tb_lastname.Text, 
                               TelNumber = tb_telnum.Text, Email = tb_email.Text });
                }
                catch (DataServiceRequestException ex)
                {
                    statusMessage = "Unable to connect to the table storage server. Please check that the service is running.<br>"
                                     + ex.Message;
                }
                lb_status.Text = statusMessage;
            }

    Запустив отладку приложения, введем необходимые данные в появившуюся веб - форму и нажмем кнопку "Add Contact".

    asp - код веб - формы данной задачи:

    <%@ Page Language="C#" 
     AutoEventWireup="true" CodeBehind="AzureTable.aspx.cs" Inherits="WebRole1.AzureTable" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <style type="text/css">
            .style1
            {
                width: 169px;
            }
        </style>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="NameOfExample" runat="server" Font-Bold="True" 
                Font-Italic="False" Font-Size="Larger" Font-Strikeout="False" 
                Font-Underline="False" Text="My Contact List - Windows Azure Table Example"></asp:Label>
            <br />
            <br />
            <asp:Label ID="ContactLabel" runat="server" Text="Contact:"></asp:Label>
            <br />
            <table style="width:100%;">
                <tr>
                    <td class="style1">
                         </td>
                    <td>
                         </td>
                </tr>
                <tr>
                    <td class="style1">
                        <asp:Label ID="lb_firstname" runat="server" Text="First Name"></asp:Label>
                    </td>
                    <td>
                        <asp:TextBox ID="tb_firstname" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td class="style1">
                        <asp:Label ID="lb_lastname" runat="server" Text="Last Name"></asp:Label>
                    </td>
                    <td>
                        <asp:TextBox ID="tb_lastname" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td class="style1">
                        <asp:Label ID="lb_telnum" runat="server" Text="Telephone Number"></asp:Label>
                    </td>
                    <td>
                        <asp:TextBox ID="tb_telnum" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td class="style1">
                        <asp:Label ID="lb_email" runat="server" Text="E-mail"></asp:Label>
                    </td>
                    <td>
                        <asp:TextBox ID="tb_email" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td class="style1">
                         </td>
                    <td>
                         </td>
                </tr>
                <tr>
                    <td class="style1">
                         </td>
                    <td>
                        <asp:Button ID="btn_add" runat="server" Height="20px" Text="Add Contact" />
                    </td>
                </tr>
                <tr>
                    <td class="style1">
                        <asp:Label ID="lb_status" runat="server"></asp:Label>
                    </td>
                    <td>
                         </td>
                </tr>
            </table>
        
        </div>
        </form>
    </body>
    </html>

    Задача 2. Просмотр данных

    Форма создана. Классы сформированы. Осталось понять добавилось ли что-либо в наше хранилище. Открыв обозреватель серверов и раскрыв последовательно вкладки "Хранилище Windows Azure", "Разработка" и "Таблицы", мы увидем созданную таблицу "Contacts".

    (рис 17.4)

    Щелкнув правой кнопкой мыши на нашей таблице и выбрав "Просмотреть таблицу", получив следующее:

    (рис 17.5)

    Как видно, данные успешно добавлены.

    Но нас интересует отображение списка контактов в рамках нашего приложения.

    Для этого добавим на веб - форму элемент управления GridView с ID = contactGV , который мы будем использовать для отображения текущих данных таблицы.

    (рис 17.6)

    asp - код для GridView:

    <asp:GridView ID="contactGV" runat="server" CellPadding="4" ForeColor="#333333" 
                            GridLines="None" onrowdeleting="contactGV_RowDeleting" 
                            onselectedindexchanged="contactGV_SelectedIndexChanged">
                            <AlternatingRowStyle BackColor="White" />
                            <Columns>
                                <asp:CommandField ButtonType="Button" SelectText="Изменить" 
                                    ShowSelectButton="True" />
                                <asp:CommandField ButtonType="Button" ShowDeleteButton="True" />
                            </Columns>
                            <EditRowStyle BackColor="#2461BF" />
                            <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
                            <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
                            <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
                            <RowStyle BackColor="#EFF3FB" />
                            <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
                            <SortedAscendingCellStyle BackColor="#F5F7FB" />
                            <SortedAscendingHeaderStyle BackColor="#6D95E1" />
                            <SortedDescendingCellStyle BackColor="#E9EBEF" />
                            <SortedDescendingHeaderStyle BackColor="#4870BE" />
                        </asp:GridView>

    Определим переменные учетной записи и контекста, до метода Page_Load:

    private CloudStorageAccount account = null;
    private ContactContext context = null;

    В метод Page_Load нашей страницы добавим следующий код, для привязки GridView к источнику данных:

    account= CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
                context = new ContactContext(account.TableEndpoint, account.Credentials);
                contactGV.DataSource = context.ContactData;
                contactGV.DataBind();

    Также в методе btn_add_Click добавим следующую строку:

    contactGV.DataBind();

    Запустив приложение, получим следующее:

    (рис 17.7)

    Как видно, при загрузке страницы мы сразу получаем и текущий список контактов. Если добавить новый контакт, то (см. 5.2) список дополнится еще одной записью.

    (рис 17.8)

    Задача 3. Редактирование и удаление сущностей

    По своей сути задачи редактирование и удаления сущностей конкретной таблицы весьма проста. Достаточно вызвать соответствующие методы класса - контекста. Однако, в качестве параметров методов выступают изменяемые сущности. Таким образом, все сводится к выделению конкретной сущности из таблицы по ее ключам секции и строки, которые, напомним, являются частями уникального ключа сущности.

    Поскольку нашей целью является демонстрация работы с Windows Azure Table, мы пойдем по самому простому пути.

    Для начала добавим на форму кнопку btn_change, невидимую при загрузке страницы.

    Данные между методами формы будем передавать при помощи сессий.

    Первая и главная задача сводится к тому, чтобы определить ключи строки и секции редактируемой сущности. Учитывая, что структура таблицы и названия параметров могут быть произвольны, за одним исключением - как раз параметров Partition Key и Row Key , добавим в метод Page_Load следующее:

    int i = 0;
    
                foreach (TableCell cell in contactGV.HeaderRow.Cells)
                {
    
                    if (cell.Text == "PartitionKey") { Session["pkindex"] = i; }
                    if (cell.Text == "RowKey") { Session["rkindex"] = i; }
                    i++;
                }

    Теперь, вне зависимости от структуры таблицы, сессии pkindex и rkindex будут содержать номера столбцов contactGV , в которых находятся параметры ключей секции и строки.

    Полностью метод Page_Load для данного задания должен быть следующим:

    protected void Page_Load(object sender, EventArgs e)
            {
                btn_change.Visible = false;
    
                account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
                context = new ContactContext(account.TableEndpoint, account.Credentials);
                contactGV.DataSource = context.ContactData;
                contactGV.DataBind();
    
                int i = 0;
    
                foreach (TableCell cell in contactGV.HeaderRow.Cells)
                {
    
                    if (cell.Text == "PartitionKey") { Session["pkindex"] = i; }
                    if (cell.Text == "RowKey") { Session["rkindex"] = i; }
                    i++;
                }
            }

    Также добавим в класс ContactContext методы для обновления и удаления сущностей - Update и Delete соответственно:

    public void Delete(Contact cnt)
            {
                this.DeleteObject(cnt);
                this.SaveChanges();
            }
    
            public void Update(Contact cnt)
            {
                this.UpdateObject(cnt);
                this.SaveChanges();
            }

    Удаление строки

    Добавим метод, обрабатывающий нажатие кнопки "Удалить" элемента contactGV.

    protected void contactGV_RowDeleting(object sender, GridViewDeleteEventArgs e)
            {
                GridView g = (GridView)sender;
                try
                {
                    Contact c = (from contact in context.CreateQuery<Contact>("Contacts")
                                 where contact.PartitionKey == g.Rows[e.RowIndex].
                                    Cells[Convert.ToInt32(Session["pkindex"].ToString())].Text
                                  contact.RowKey == g.Rows[e.RowIndex].Cells[Convert.ToInt32
                                   (Session["rkindex"].ToString())].Text
                                 select contact).FirstOrDefault();
    
                    context.Delete(c);
                }
                catch(DataServiceRequestException ex) 
                {
                    lb_status.Text = ex.Message;
                }
              g.DataBind();
      
             }

    Обратим ваше внимание на то, что сущность для удаления мы получаем при помощи linq - запроса, указывая значения параметров PartitionKey и RowKey . Значения же параметров мы получаем из contactGV , указывая значения соответствующих ячеек.

    Реализация удаления сущности на этом закончена.

    Редактирование сущности

    Для начала напишем обработчик события изменения индекса выбранной строки contactGV , инициируемое нажатием кнопки "Изменить" . При нажатии этой кнопки должен становиться видимым элемент управления btn_change, а соответствующие текстовые поля заполняться значениями параметров редактируемой строки.

    protected void contactGV_SelectedIndexChanged(object sender, EventArgs e)
            {
                GridView g = (GridView)sender;
                int index = g.SelectedIndex;
    
                Contact c = (from contact in context.CreateQuery<Contact>("Contacts")
                             where contact.PartitionKey == g.Rows[index].
                                 Cells[Convert.ToInt32(Session["pkindex"].ToString())].Text
                              contact.RowKey == g.Rows[index].
                                 Cells[Convert.ToInt32(Session["rkindex"].ToString())].Text
                             select contact).FirstOrDefault();
                tb_firstname.Text = c.FirstName;
                tb_lastname.Text = c.LastName;
                tb_email.Text = c.Email;
                tb_telnum.Text = c.TelNumber;
    
                Session["index"] = index;
    
                btn_change.Visible = true;
            }

    Здесь стоит обратить внимание разве что на формирование еще одной сессии, в которой мы будем хранить номер редактируемой строки в contactGV.

    Вот, что должно получиться при нажатии кнопки "Изменить" напротив второй строки списка контактов:

    (рис 17.9)

    Как видим, значения текстовых полей стали соответствовать значениям параметров редактируемой строки.

    Осталось только написать метод обрабатывающий событие нажатия кнопки btn_change.

    Он будет выглядеть следующим образом:

    protected void btn_change_Click(object sender, EventArgs e)
            {
                
                int index = Convert.ToInt32(Session["index"].ToString());
                try
                {
                Contact c = (from contact in context.CreateQuery<Contact>("Contacts")
                             where contact.PartitionKey == contactGV.Rows[index].
                                  Cells[Convert.ToInt32(Session["pkindex"].ToString())].Text
                              contact.RowKey == contactGV.Rows[index].
                                  Cells[Convert.ToInt32(Session["rkindex"].ToString())].Text
                             select contact).FirstOrDefault();
    
                c.FirstName = tb_firstname.Text;
                c.LastName = tb_lastname.Text;
                c.Email = tb_email.Text;
                c.TelNumber = tb_telnum.Text;
    
               
                    context.Update(c);
                    
                }
                catch (DataServiceRequestException a)
                {
                    lb_status.Text = a.Message;
                }
                contactGV.DataBind();
    
            }

    Номер изменяемой строки мы получаем из сессии "index" , остальное уже не должно вызывать вопросов.

    Запустите приложение еще раз и измените произвольным образом любой из параметров, либо насколько из них какой - либо строки. Мы изменили Email на tableentitychange@mail.test . Нажмите кнопку "Change".

    Мы получили следующее:

    (рис 17.10)

    Еще раз обратим ваше внимание на то, что демонстрируемое приложение является не более, чем примером способов работы с Windows Azure Storage, поэтому мы пренебрегли обработкой исключительных ситуаций и проверкой правильности и целостности введенных данных. Оставляем это на ваше усмотрение.

    В случае, если выполнение задания вызвало сложности и затруднения, в приложениях к данной практической работе вы найдете итоговый программный код в том виде, в котором он необходим для Задания№3.

    Список вспомогательных материалов

    Работа с Windows Azure Table

  • http://msdn.microsoft.com/ru-ru/magazine/gg309178.aspx
  • http://msdn.microsoft.com/en-us/wazplatformtrainingcourse_exploringwindowsazurestoragevs2010_topic2#_Toc282791662
  • http://blogs.msdn.com/b/morebits/archive/2010/12/26/building-windows-azure-service-part3-table-storage.aspx
  • Приложение А. ASP - код веб - формы (AzureTable.aspx)

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AzureTable.aspx.cs" Inherits="WebRole1.AzureTable" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <style type="text/css">
            .style1
            {
            }
            .style2
            {
                width: 149px;
            }
        </style>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
        
            <asp:Label ID="NameOfExample" runat="server" Font-Bold="True" 
                Font-Italic="False" Font-Size="Larger" Font-Strikeout="False" 
                Font-Underline="False" Text="My Contact List - Windows Azure Table Example"></asp:Label>
            <br />
            <br />
            <asp:Label ID="ContactLabel" runat="server" Text="Contact:"></asp:Label>
            <br />
            <table style="width:100%;">
                <tr>
                    <td class="style2">
                         </td>
                    <td>
                         </td>
                </tr>
                <tr>
                    <td class="style2">
                        <asp:Label ID="lb_firstname" runat="server" Text="First Name"></asp:Label>
                    </td>
                    <td>
                        <asp:TextBox ID="tb_firstname" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td class="style2">
                        <asp:Label ID="lb_lastname" runat="server" Text="Last Name"></asp:Label>
                    </td>
                    <td>
                        <asp:TextBox ID="tb_lastname" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td class="style2">
                        <asp:Label ID="lb_telnum" runat="server" Text="Telephone Number"></asp:Label>
                    </td>
                    <td>
                        <asp:TextBox ID="tb_telnum" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td class="style2">
                        <asp:Label ID="lb_email" runat="server" Text="E-mail"></asp:Label>
                    </td>
                    <td>
                        <asp:TextBox ID="tb_email" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td class="style2">
                         </td>
                    <td>
                         </td>
                </tr>
                <tr>
                    <td class="style2">
                        <asp:Button ID="btn_change" runat="server" onclick="btn_change_Click" 
                            Text="Change" Width="105px" />
                    </td>
                    <td>
                        <asp:Button ID="btn_add" runat="server" Height="20px" onclick="btn_add_Click" 
                            Text="Add Contact" />
                    </td>
                </tr>
                <tr>
                    <td class="style2">
                        <asp:Label ID="lb_status" runat="server"></asp:Label>
                    </td>
                    <td>
                         </td>
                </tr>
                <tr>
                    <td class="style2">
                         </td>
                    <td>
                         </td>
                </tr>
                <tr>
                    <td class="style1" colspan="2">
                        <asp:GridView ID="contactGV" runat="server" CellPadding="4" ForeColor="#333333" 
                            GridLines="None" onrowdeleting="contactGV_RowDeleting" 
                            onselectedindexchanged="contactGV_SelectedIndexChanged">
                            <AlternatingRowStyle BackColor="White" />
                            <Columns>
                                <asp:CommandField ButtonType="Button" SelectText="Изменить" 
                                    ShowSelectButton="True" />
                                <asp:CommandField ButtonType="Button" ShowDeleteButton="True" />
                            </Columns>
                            <EditRowStyle BackColor="#2461BF" />
                            <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
                            <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
                            <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
                            <RowStyle BackColor="#EFF3FB" />
                            <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
                            <SortedAscendingCellStyle BackColor="#F5F7FB" />
                            <SortedAscendingHeaderStyle BackColor="#6D95E1" />
                            <SortedDescendingCellStyle BackColor="#E9EBEF" />
                            <SortedDescendingHeaderStyle BackColor="#4870BE" />
                        </asp:GridView></td>
                </tr>
            </table>
        
        </div>
        </form>
    </body>
    </html>

    Приложение Б. Класс Contact.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace WebRole1
    {
        class Contact : Microsoft.WindowsAzure.StorageClient.TableServiceEntity
        {
            public String FirstName { get; set; }
            public String LastName { get; set; }
            public String TelNumber { get; set; }
            public String Email { get; set; }
        }
    }

    Приложение В. Класс ContactContext.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.StorageClient;
    using System.Data.Services.Client;
    
    namespace WebRole1
    {
        class ContactContext : TableServiceContext
        {
    
            public IQueryable<Contact> ContactData
            {
                get
                {
                    return this.CreateQuery<Contact>("Contacts");
    
                }
            }
    
            public ContactContext(Uri baseAddress, StorageCredentials credentials) : base(baseAddress.AbsoluteUri, credentials) { }
    
            public void Add(Contact cnt)
            {
                this.AddObject("Contacts", cnt);
                this.SaveChanges();
            }
    
            public void Delete(Contact cnt)
            {
                this.DeleteObject(cnt);
                this.SaveChanges();
            }
    
            public void Update(Contact cnt)
            {
                this.UpdateObject(cnt);
                this.SaveChanges();
            }
        }
    }

    Приложение Г. Global.asax.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.SessionState;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.StorageClient;
    using System.Data.Services.Client;
    using Microsoft.WindowsAzure.ServiceRuntime;
    
    namespace WebRole1
    {
        public class Global : System.Web.HttpApplication
        {
    
            void Application_Start(object sender, EventArgs e)
            {
    
                CloudStorageAccount.SetConfigurationSettingPublisher(
                    (configName, configSettingPublisher) =>
                    {
                        var connectionString =
                            RoleEnvironment.GetConfigurationSettingValue(configName);
                        configSettingPublisher(connectionString);
                    }
                ); 
    
                var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
    
                CloudTableClient _tc = null;
                _tc = account.CreateCloudTableClient();
                _tc.CreateTableIfNotExist("Contacts");
    
    
            }
    
            void Application_End(object sender, EventArgs e)
            {
      
            }
    
            void Application_Error(object sender, EventArgs e)
            {
    
            }
    
            void Session_Start(object sender, EventArgs e)
            {
    
            }
    
            void Session_End(object sender, EventArgs e)
            {
    
            }
    
        }
    }

    Приложение Д. AzureTable.aspx.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Data.Services.Client;
    using Microsoft.WindowsAzure;
    
    namespace WebRole1
    {
        public partial class AzureTable : System.Web.UI.Page
        {
            private CloudStorageAccount account = null;
            private ContactContext context = null;
    
            protected void Page_Load(object sender, EventArgs e)
            {
                btn_change.Visible = false;
    
                account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
                context = new ContactContext(account.TableEndpoint, account.Credentials);
                contactGV.DataSource = context.ContactData;
                contactGV.DataBind();
    
                int i = 0;
    
                foreach (TableCell cell in contactGV.HeaderRow.Cells)
                {
    
                    if (cell.Text == "PartitionKey") { Session["pkindex"] = i; }
                    if (cell.Text == "RowKey") { Session["rkindex"] = i; }
                    i++;
                }
            }
    
            protected void btn_add_Click(object sender, EventArgs e)
            {
                var statusMessage = String.Empty;
                try
                {
    
                    context.Add(new Contact { PartitionKey = "MyContacts", 
                     RowKey = this.tb_lastname.Text + " " + this.tb_firstname.Text, 
                      FirstName = tb_firstname.Text, LastName = tb_lastname.Text, 
                        TelNumber = tb_telnum.Text, Email = tb_email.Text });
                   
                }
                catch (DataServiceRequestException ex)
                {
                    statusMessage = "Unable to connect to the table storage server. Please check that the service is running.<br>"
                                     + ex.Message;
                }
                lb_status.Text = statusMessage;
                contactGV.DataBind();
            }
    
            protected void contactGV_RowDeleting(object sender, GridViewDeleteEventArgs e)
            {
    
                GridView g = (GridView)sender;
                try
                {
                    Contact c = (from contact in context.CreateQuery<Contact>("Contacts")
                                 where contact.PartitionKey == g.Rows[e.RowIndex].
                                  Cells[Convert.ToInt32(Session["pkindex"].ToString())].Text
                                  contact.RowKey == g.Rows[e.RowIndex].
                                  .Cells[Convert.ToInt32(Session["rkindex"].ToString())].Text
                                 select contact).FirstOrDefault();
    
                    context.Delete(c);
                }
                catch(DataServiceRequestException ex) 
                {
                    lb_status.Text = ex.Message;
                }
              g.DataBind();
    
            }
    
            protected void contactGV_SelectedIndexChanged(object sender, EventArgs e)
            {
                GridView g = (GridView)sender;
                int index = g.SelectedIndex;
    
                Contact c = (from contact in context.CreateQuery<Contact>("Contacts")
                             where contact.PartitionKey == g.Rows[index].Cells[Convert.ToInt32(Session["pkindex"].ToString())].Text
                              contact.RowKey == g.Rows[index].Cells[Convert.ToInt32(Session["rkindex"].ToString())].Text
                             select contact).FirstOrDefault();
                tb_firstname.Text = c.FirstName;
                tb_lastname.Text = c.LastName;
                tb_email.Text = c.Email;
                tb_telnum.Text = c.TelNumber;
    
                Session["index"] = index;
    
                btn_change.Visible = true;
            }
    
            protected void btn_change_Click(object sender, EventArgs e)
            {
                
                int index = Convert.ToInt32(Session["index"].ToString());
                try
                {
                Contact c = (from contact in context.CreateQuery<Contact>("Contacts")
                             where contact.PartitionKey == contactGV.Rows[index].
                                 Cells[Convert.ToInt32(Session["pkindex"].ToString())].Text
                              contact.RowKey == contactGV.Rows[index].
                                 Cells[Convert.ToInt32(Session["rkindex"].ToString())].Text
                             select contact).FirstOrDefault();
    
                c.FirstName = tb_firstname.Text;
                c.LastName = tb_lastname.Text;
                c.Email = tb_email.Text;
                c.TelNumber = tb_telnum.Text;
    
               
                    context.Update(c);
                    
                }
                catch (DataServiceRequestException a)
                {
                    lb_status.Text = a.Message;
                }
                contactGV.DataBind();
    
            }
        }
    }
    Вернуться к учебному плану