При загрузке данных из БД возникает исключение InvalidOperationException с сообщением: Элемент коллекции должен быть пустым перед использованием ItemsSource. Знаю, что для заполнения DataGrid можно использовать коллекции Items или ItemsSource, но одновременно их использовать нельзя: если задано значение для свойства ItemsSource и в коде C# добавляется элемент в Items, возникает исключение. |
Разработка Silverlight-приложения
Задание 5. Разработать методы манипулирования данными – 2 часа.
Редактирование данных
Для редактирования данных необходимо обеспечить возможность изменения детальных данных, что реализуется нажатием кнопки Редактировать. С учетом того, что для элементов управления детальными данными выполнена двусторонняя привязка данных ( Mode=TwoWay ), то изменения в детальных данных будут приводить к изменению данных в контексте сущностей, связанных со списком listBox. После редактирования данных необходимо проведенные изменения сохранить в базе данных. Для этого модифицируйте метод Save_Click, добавив в него следующую строку:
context.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, context);
Измененный код метода Save_Click будет иметь следующий вид:
private void Save_Click(object sender, RoutedEventArgs e) { context.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, context); ReadOnly(false); ButtonIsEnabled(true); listBoxEmployees.IsEnabled = true; }
Метод BeginSaveChanges() класса DataServiceContent запускает асинхронную операцию сохранения данных, изменение которых были проведены в контексте сущностей PersonalEntities. Перечисление SaveChangesOptions.Batch определяет, что все проведенные изменения сохраняются в составе одного пакетного запроса. Вторым параметром метода BeginSaveChanges() является делегат, который ссылается на метод OnChangesSaved(). Метод OnChangesSaved() обрабатывает результат этой асинхронной операции путем вызова метода EndSaveChanges(), анализа возвращаемых объектов OperationResponse и печати кодов состояния ответа.
private void OnChangesSaved(IAsyncResult result) { Dispatcher.BeginInvoke(() => { context = result.AsyncState as PersonalEntities; try { WriteOperationResponse(context.EndSaveChanges(result)); } catch (DataServiceRequestException ex) { MessageBox.Show( WriteOperationResponse(ex.Response)); } catch (InvalidOperationException ex) { MessageBox.Show(ex.Message); } } ); }
Метод WriteOperationResponse() обеспечивает формирование информации при сохранении данных.
private string WriteOperationResponse(DataServiceResponse response) { string mes = string.Empty; int i = 1; if (response.IsBatchResponse) { mes = string.Format("Коды серии операций сохранения: {0}\n", response.BatchStatusCode); } foreach (ChangeOperationResponse change in response) { mes += string.Format("\tИзменение {0} code: {1}\n", i.ToString(), change.StatusCode.ToString()); if (change.Error != null) { string.Format("\tИзменение {0} error: {1}\n", i.ToString(), change.Error.Message); } i++; } return mes; }
Проведенные изменения обеспечивают для разрабатываемого приложения возможность редактирования данных и сохранение изменений в базе данных.
Создание новых данных
Создание новых записей в базе данных рассматривается на примере базы Personal.
Для создания новых записей в базе данных изменим код метода New_Click().
private void New_Click(object sender, RoutedEventArgs e) { Employee newEmployee = Employee.CreateEmployee(0, "не задано", "не задано", 0, "не задано"); newEmployee.Access = "не задано"; newEmployee.EmployeeStatus = 0; newEmployee.NetName = "guest"; newEmployee.FirstDate = DateTime.Now; try { context.AddToEmployees(newEmployee); context.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, context); employees.Add(newEmployee); int count = listBoxEmployees.Items.Count; listBoxEmployees.SelectedIndex = count - 1; ButtonIsEnabled(false); ReadOnly(true); listBoxEmployees.IsEnabled = false; } catch (DataServiceRequestException ex) { MessageBox.Show("Ошибка добавления нового сотрудника в базу данных"); } }
Вначале для класса Employee модели сущностей Personal создайте новый экземпляр newEmployee с помощью метода CreateEmployee():
Employee newEmployee=Employee.CreateEmployee(0, "не задано","не задано",0,"не задано");
Метод CreateEmployee() автоматически сгенерирован при создании EDM-модели сущностей и в качестве параметров использует только обязательные поля таблицы Employee базы данных Personal. Следующие строки кода предназначены для задания необязательных полей таблицы Employee ( Access, EmployeeStatus, NetName и FirstDate ):
newEmployee.Access = "не задано"; newEmployee.EmployeeStatus = 0; newEmployee.NetName = "guest"; newEmployee.FirstDate = DateTime.Now;
Добавьте новую сущность newEmployee в модель Personal:
context.AddToEmployees(newEmployee);
при этом используется метод AddToEmployees().
Затем посредством метода BeginSaveChanges() класса DataServiceContent проведите сохранение данных в контексте сущностей PersonalEntities.
context.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, context);
Для продолжения работы приложения необходимо внести изменения в коллекцию employees.
employees.Add(newEmployee);
и установить фокус в списке listBoxEmployees на созданной записи:
int count = listBoxEmployees.Items.Count; listBoxEmployees.SelectedIndex = count - 1;
Удаление данных по сотруднику
Для удаления данных в базе данных необходимо определить экземпляр удаляемого объекта, например из списка listBox.
Employee emp = (Employee)listBoxEmployees.SelectedItem;
Затем удалить экземпляр класса Employee из контекста сущностей PersonalEntities с помощью метода DeleteObject().
context.DeleteObject(emp);
После изменения индекса выделения в списке listBoxEmployees необходими удалить экземпляр emp класса Employee из коллекции employees.
listBoxEmployees.SelectedIndex = listBoxEmployees.SelectedIndex == 0 ? 1 : listBoxEmployees.SelectedIndex - 1; employees.Remove(emp);
Посредством метода BeginSaveChanges() класса DataServiceContent запустите сохранение изменений при удалении данных из контекста сущностей PersonalEntities.
context.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, context);
Окончательный код метода Delete_Click() будет иметь следующий вид.
private void Delete_Click(object sender, RoutedEventArgs e) { Employee emp = (Employee)listBoxEmployees.SelectedItem; MessageBoxResult result = MessageBox.Show("Удалить сотрудника: " + emp.EmployeeSurname + " " + emp.EmployeeName + " " + emp.EmployeePatronymic, "Предупреждение", MessageBoxButton.OKCancel); if (result == MessageBoxResult.OK) { context.DeleteObject(emp); listBoxEmployees.SelectedIndex = listBoxEmployees.SelectedIndex == 0 ? 1 : listBoxEmployees.SelectedIndex - 1; employees.Remove(emp); context.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, context); } }