Опубликован: 08.07.2011 | Уровень: для всех | Доступ: платный
Лекция 5:

Взаимодействие приложения с базой данных

Редактирование, вставка и удаление данных

Для редактирования данных в приложении модифицируем метод EditCommandBinding_Executed

private void EditCommandBinding_Executed(object sender, 
ExecutedRoutedEventArgs e)
{
    DataGridEmployee.IsReadOnly = false;
    DataGridEmployee.BeginEdit();
    isDirty = false;
}

Свойству IsReadOnly сетки DataGridEmployee присвоим значение false, что обеспечит возможность редактирования строк и ячеек сетки. Далее используем метод BeginEdit для начала редактирования ячейки, на которую наведен указатель мыши.

Результаты редактирования необходимо сохранить в базе данных. Для этого необходимо вызвать метод SaveCommandBinding_Executed.

private void SaveCommandBinding_Executed(object sender, 
ExecutedRoutedEventArgs e)
{
    DataEntitiesEmployee.SaveChanges();
    isDirty = true;
    DataGridEmployee.IsReadOnly = true;
}

В методе SaveCommandBinding_Executed вызывается метод SaveChanges класса dataEntitiesEmployee. Метод SaveChanges сохраняет все обновления в источнике данных.

Для создания данных по новому сотруднику модифицируем метод NewCommandBinding_Executed.

private void NewCommandBinding_Executed(object sender, 
                                        ExecutedRoutedEventArgs e)
{
    Employee employee = Employee.CreateEmployee(-1, "не задано", 
	                                            "не задано", "не задано", 0);
    employee.Telephone = "не задано";
    employee.Email = "не задано";
    try
    {
        DataEntitiesEmployee.Employees.AddObject(employee);
        ListEmployee.Add(employee);
        DataGridEmployee.ScrollIntoView(employee);
        DataGridEmployee.SelectedIndex = DataGridEmployee.Items.Count - 1;
        DataGridEmployee.Focus();
        DataGridEmployee.IsReadOnly = false;
        isDirty = false;
    }
    catch (DataServiceRequestException ex)
    {
        throw new ApplicationException(
"Ошибка добавления нового сотрудника в контекст данных" + ex.ToString());
    }
}

В методе NewCommandBinding_Executed объект employee класса Employee создается с помощью метода CreateEmployee, параметрами которого являются ID, которое задается равным -1, Surname, Name и Patronymic, которым задается значение "не задано" и TitleID со значением 0. Кроме того, свойствам Telephone и Email объекта employee присваивается строковое значение "не задано". В блоке try ... catch созданный объект employee добавляется в контекст данных методом AddObject сущности Employees EDM-модели DataEntitiesEmployee, а также в коллекцию ListEmployee. Затем производится прокрутка сетки, выделение и перемещение фокуса на созданный объект.

DataGridEmployee.ScrollIntoView(employee);
DataGridEmployee.SelectedIndex = DataGridEmployee.Items.Count - 1;
DataGridEmployee.Focus();

При инициализации команды создания данных по новому сотруднику в сетке формируется первоначальная строка с данными "по умолчанию" ( рис. 5.12). В сформированную строку необходимо ввести реальные данные сохранить их, вызвав команду "Сохранить".

Формирование данных по новому сотруднику

увеличить изображение
Рис. 5.12. Формирование данных по новому сотруднику

Для удаления данных по сотруднику используем метод DeleteCommandBinding_Executed.

private void DeleteCommandBinding_Executed(object sender, 
									ExecutedRoutedEventArgs e)
{
    Employee emp = DataGridEmployee.SelectedItem as Employee;
    if (emp != null)
    {
        MessageBoxResult result = MessageBox.Show("Удалить сотрудника: " + 
emp.Surname + " " +emp.Name + " " + emp.Patronymic, 
"Предупреждение", MessageBoxButton.OKCancel);
        if (result == MessageBoxResult.OK)
        {
            DataEntitiesEmployee.DeleteObject(emp);
            DataGridEmployee.SelectedIndex =
             DataGridEmployee.SelectedIndex == 0 ? 1 : DataGridEmployee.SelectedIndex - 1;
            ListEmployee.Remove(emp);
            DataEntitiesEmployee.SaveChanges();
        }
    }
    else
    {
        MessageBox.Show("Выберите строку для удаления");
    }
}

В методе определяем объект emp класса Employee, который выделен в сетке DataGridEmployee.

Employee emp = DataGridEmployee.SelectedItem as Employee;

Если объект emp найден, то с помощью диалогового окна класса MessageBoxResult выводим сообщение с данными о сотруднике, которого предполагается удалить.

MessageBoxResult result = MessageBox.Show("Удалить сотрудника: " + 
emp.Surname + " " + emp.Name + " " + emp.Patronymic, "Предупреждение", MessageBoxButton.OKCancel);

При подтверждении операции удаления объект emp удаляется из контекста методом DeleteObject.

DataEntitiesEmployee.DeleteObject(emp);

Далее формируется в сетке DataGridEmployee выделяемая строка.

DataGridEmployee.SelectedIndex =
            DataGridEmployee.SelectedIndex == 0 ? 1 : DataGridEmployee.SelectedIndex - 1;

Объект emp удаляется из коллекции ListEmployee.

ListEmployee.Remove(emp);

Изменения вносятся в базу данных.

DataEntitiesEmployee.SaveChanges();

Страница PageEmployee при выполнении операции удаления данных по сотруднику приведена на рис. 5.13.

Удаление данных по сотруднику

увеличить изображение
Рис. 5.13. Удаление данных по сотруднику

Метод UndoCommandBinding_Executed реализует отмену редактирования последних элементов сетки DataGridEmployee и переводит её в режим просмотра.

Для реализации данной функциональности необходимо провести некоторые изменения в коде приложения. Для метода Page_Loaded основной код выделим в метод GetEmployees.

private void GetEmployees()
{
    ObjectQuery<Employee> employees = DataEntitiesEmployee.Employees;
    var queryEmployee = from employee in employees
                        orderby employee.Surname
                        select employee;
    foreach (Employee emp in queryEmployee)
    {
        ListEmployee.Add(emp);
    }
    DataGridEmployee.ItemsSource = ListEmployee;
}

С учетом созданного метода GetEmployees метод Page_Loaded будет иметь следующий вид.

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    GetEmployees();
    DataGridEmployee.SelectedIndex = 0;
}

Создадим метод RewriteEmployee, который будет обновлять контекст данных и коллекцию ListEmployee.

private void RewriteEmployee()
{
    DataEntitiesEmployee = new TitlePresonalEntities();
    ListEmployee.Clear();
    GetEmployees();
}

С учетом проведенных модификаций кода метод UndoCommandBinding_Executed будет иметь следующий вид.

private void UndoCommandBinding_Executed(object sender, 
ExecutedRoutedEventArgs e)
{
    RewriteEmployee();
    DataGridEmployee.IsReadOnly = true;
    isDirty = true;
}

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

Александр Петров
Александр Петров

При загрузке данных из БД возникает исключение InvalidOperationException с сообщением: Элемент коллекции должен быть пустым перед использованием ItemsSource. Знаю, что для заполнения DataGrid можно использовать коллекции Items или ItemsSource, но одновременно их использовать нельзя: если задано значение для свойства ItemsSource и в коде C# добавляется элемент в Items, возникает исключение. 
Вопрос, как отследить и отключить добавление элемента в Items?

Максим Спиридонов
Максим Спиридонов

В пятой лекции на второй странице в компиляторе выскакивает ошибка в строчке :

ObjectQuery<Employee> employees = DataEntitiesEmployee.Employees;

Ошибка CS0029

Не удается неявно преобразовать тип "System.Data.Entity.DbSet<WpfApplProject.Employee>" в "System.Data.Entity.Core.Objects.ObjectQuery<WpfApplProject.Employee>".

в using прописал все как положено, здесь похоже именно с преобразованием типов проблемы

Igor Chelyadinski
Igor Chelyadinski
Беларусь, Минск, №54, 2013
Валентина Алешина
Валентина Алешина
Россия