Проекция Automapper с OData работает нормально, как и ожидалось, но если я получаю класс из DTO, это вызывает следующую ошибку:
"exceptionMessage": "The 'TypeIs' expression with an input of type 'EmployeeDTO' and a check of type 'DeveloperDTO' is not supported. Only entity types and complex types are supported in LINQ to Entities queries.",
"exceptionType": "System.NotSupportedException",
Ирония заключается в том, что производный класс не используется в проекции и даже не отображается.
Чтобы лучше понять проблему, я смог упростить задачу, используя базу данных «Борей». Вот код:
public class EmployeeDTO
{
public int EmployeeID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
}
public class DeveloperDTO : EmployeeDTO
{
}
public class EmployeesController : ApiController
{
[HttpGet]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.Select)]
public IHttpActionResult Get()
{
Mapper.CreateMap<Employee, EmployeeDTO>();
var dbContext = new NORTHWNDEntities();
var models = dbContext.Employees;
var dtos = models.Project().To<EmployeeDTO>();
return Ok(dtos);
}
}
Вызов этого контроллера с помощью этого вызова OData вызывает ошибку:
http://<hostname>/api/employees/get?$select=LastName
Это происходит только при использовании функции выбора OData. Другие, которые я пробовал (skip, top, orderby), все работают без проблем.
А теперь самое интересное. Просто закомментируйте базовый класс (EmployeeDTO) определения класса DeveloperDTO, и функция выбора OData работает просто отлично. Как видите, ничто даже не использует класс DeveloperDTO. Он не нанесен на карту, абсолютно не используется во всем проекте.
Это касается Visual Studio 2013, .NET4.5, Wep API 2.2, Automapper 3.3.1 и Microsoft ASP.NET Web API 2.2 для OData 4.0 v5.4.
Воссоздайте проблему:
- Создайте новое приложение Web API 2.
- Добавьте новый элемент «Модель данных объекта ADO.NET» и выберите «Конструктор EF из базы данных». Выберите базу данных "Борей" и только выберите таблицу "Сотрудники" (Борей не поддерживает Entity Framework).
- С помощью Nuget добавьте «Automapper» и «Microsoft ASP.NET Web API 2.2 для OData 4.0».
- Добавьте новый элемент «WEb API 2 Controller — Empty» и назовите его «EmployeesController». Замените класс по умолчанию кодом, указанным выше. Не забудьте включить два класса DTO.
Запустите это приложение с указанным выше URL-адресом, и вы получите сообщение об ошибке. Закомментируйте класс DeveloperDTO, и вы не получите ошибку.
Временное исправление: если я не создам какой-либо класс из DTO и продублирую все члены во всех классах, которые были бы производными от DTO, тогда все будет работать так, как ожидалось. Однако для обслуживания я бы предпочел использовать наследование.
Я углубился в код MS Odata, но он быстро становится волосатым, очень трудно следить за потоком, и я не мог понять лямбду, которую он применял к запрашиваемому, чтобы попытаться воссоздать проблему без «магии» веб-API. и оформление OData.
Я нашел много сообщений на SO о проекции Automapper и OData в отношении составных DTO, но ни один из них не выглядит применимым к этому случаю.
Любая помощь будет оценена. Спасибо искренне!