|
При загрузке данных из БД возникает исключение 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);
}
}