реляционные данные в asp.net mvc - PullRequest
0 голосов
/ 25 июня 2018

Я получаю 500 внутреннюю ошибку сервера, когда вызывается метод для данных реляционной таблицы (Сотрудник и отдел 0/1 для многих) для возврата как jsonresult. Есть метод, который получает ошибку,

public JsonResult Index()
    {
        var employee = db.Employees.Include(x=>x.Department).ToList();
        return Json(employee, JsonRequestBehavior.AllowGet);
    }

, ноесли я преобразую его следующим образом, он работает нормально.

public JsonResult Index()
    { var emplist = db.Employees.ToList();
      EmployeeViewModel emp = new EmployeeViewModel();
      List<EmployeeViewModel> employee = emplist.Select(x => new EmployeeViewModel
      { EmployeeId = x.EmployeeId, 
        EmployeeName = x.EmployeeName, 
        DepartmentId = x.DepartmentId,
        DepartmentName = x.Department.DepartmentName }).ToList();
        return Json(employee, JsonRequestBehavior.AllowGet);
}

Есть ли способ заставить первый метод работать ..?

1 Ответ

0 голосов
/ 26 июня 2018

Ошибка, которую вы, вероятно, получаете, связана с тем, что MVC пытается сериализовать вашу сущность для передачи клиенту, и контекст БД вышел из области видимости.(Неясно, как DbContext ограничен предоставленным вами кодом.) Сериализация будет перебирать все свойства в сущности, а для ссылок с отложенной загрузкой она будет пытаться загрузить их одну за другой.Даже если DbContext ограничен запросом и доступен, это очень неэффективно.

Чтобы избежать подобных проблем, просто не передайте объекты EF между сервером и клиентом.Ничего хорошего из этого не выйдет.Передайте модель представления, которая представляет только те данные, которые необходимы вашему представлению.

Когда вы делаете:

var emplist = db.Employees.ToList(); 
// ^ Hits the database and loads ALL employees with all fields. (Does not load referenced data associated to employees, such as the departments.)

      Employee emp = new Employee();
// ^ Does absolutely nothing for your cause.

      List<Employee> employee = emplist.Select(x => new Employee
      { EmployeeId = x.EmployeeId, 
        EmployeeName = x.EmployeeName, 
        DepartmentId = x.DepartmentId,
        DepartmentName = x.Department.DepartmentName }).ToList();
// ^ Selects 3 fields from each employee, then lazy-loads the department (works because the dbContext is in scope) and selects 1 field from the department. By using "new Employee" you are creating a POCO of the employee, not an EF proxy so the serializer will *not* attempt to resolve any dependencies.

        return Json(employee, JsonRequestBehavior.AllowGet);
// ^ Serializes the POCO Employee object.

Вместо этого, лучшим решением будет объявление EmployeeViewModel с EmployeeId, EmployeeName, DepartmentId, и DepartmentName, затем используйте следующее.

var employeeViewModels = db.Employees
  .Select(x => new EmployeeViewModel 
    {
      EmployeeId = x.EmployeeId,
      EmployeeName = x.EmployeeName,
      DepartmentId = x.Department.DepartmentId,
      DepartmentName = x.Department.DepartmentName
    }).ToList();
return Json(employeeViewModels, JsonRequestBehavior.AllowGet);

Это заполнит ваши модели представлений одним попаданием в базу данных, возвращая только 4 поля, которые вы хотите передать в представление, вместо загрузки каждого поля в Employee.плюс дополнительный вызов БД для загрузки отдела.Модель представления - это просто POCO, поэтому при сериализации нет странного поведения.Вы можете заполнить сущность Employee, однако я бы рекомендовал избегать этого, потому что это может сбивать с толку при работе с сущностью, которая может быть прокси-сервером EF (отключение ленивых загрузок) по сравнению с сущностью POCO, в которой будет отсутствовать информация и EFконтекст ничего не знает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...