Работа с Windows Azure Table
Задача 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.
Вот, что должно получиться при нажатии кнопки "Изменить" напротив второй строки списка контактов:
Как видим, значения текстовых полей стали соответствовать значениям параметров редактируемой строки.
Осталось только написать метод обрабатывающий событие нажатия кнопки 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".
Мы получили следующее:
Еще раз обратим ваше внимание на то, что демонстрируемое приложение является не более, чем примером способов работы с Windows Azure Storage, поэтому мы пренебрегли обработкой исключительных ситуаций и проверкой правильности и целостности введенных данных. Оставляем это на ваше усмотрение.
В случае, если выполнение задания вызвало сложности и затруднения, в приложениях к данной практической работе вы найдете итоговый программный код в том виде, в котором он необходим для Задания№3.