Запрос NHibernate выполняется только один раз, затем генерирует исключение InvalidCastException
У меня есть простой запрос, как показано ниже:
var employeeTeam = Session.Query<EmployeeTeam>()
.Where(x => x.StartEffective <= competency.FinalDate && // competency.FinalDate is a DateTime
employeesIds.Contains(x.EmployeeId)) // employeeIds is a List<long>
.OrderByDescending(x => x.StartEffective)
.Select(x => new
{
x.EmployeeId,
x.StartEffective,
x.Team
}).ToList();
Он успешно запускается один раз, но при выполнении во второй раз (или третий, четвертый и т. Д.) Он генерирует недопустимое исключение приведения типа:
Неустранимая ошибка:System.InvalidCastException: невозможно преобразовать тип 'System.Linq.EnumerableQuery`1[<>f__AnonymousType0`3[System.Int64,System.DateTime,Team]]' в 'System.Collections.Generic.IEnumerable`1[<>f__AnonymousType0`3[System.Int64,System.DateTime,Team]]. в NHibernate.Linq.DefaultQueryProvider.Execute[TResult](выражение выражения)
Остальная часть трассы стека подавлена для смелых.
Запрос всегда выполняется в базе данных до ошибки. Он не возвращает никаких записей, но это нормально. Если я перестраиваю решение и запускаю снова, запрос выполняется снова в первый раз, а затем начинает выдавать исключение каждый раз, когда я его запускаю. Другие запросы выполняются каждый раз без каких-либо проблем. Я понятия не имею, что вызывает ошибку.
Важно сказать, что этот код выполняется в среде CSharpCodeProvider, но я не знаю, может ли это изменить ситуацию.
ОБНОВИТЬ
Это происходит даже с самой простой формой запроса:
var employeeTeam = Session.Query<EmployeeTeam>()
.Select(x => new
{
x.Id
}).ToList();
Он работает нормально только в первый раз. Но если я изменю объект annon с { x.Id }
в { x.TeamId }
Например, он запускается нормально в первый раз, затем исключения возникают снова.
ОБНОВЛЕНИЕ 2
Я просто понимаю, что если я добавлю следующее свойство к объекту annon, запрос будет работать каждый раз:
Rnd = (new Random().Next(1, 999))
Итак, проблема с кешем может быть?
ОБНОВЛЕНИЕ 3
Я обновил NHibernate от 3.3
в 4.0.0.4
и это решает почти все проблемы, кроме одного запроса:
var query = session.Query<Holiday>()
.Select(x => new {
HoliDayCities = x.City.Select(c => c.Id).ToList(),
HoliDayStates = x.State.Select(s => s.Id).ToList(),
Date = new DateTime((int)(x.Year.HasValue ? x.Year : competencia.InitialDate.Year), (int)x.Month, (int)x.Day)
}).ToList();
Сообщение об ошибке:
GenericADOException: значение "{ HoliDayCities = System.Collections.Generic.List`1[System.Int64], HoliDayStates = System.Collections.Generic.List`1[System.Int64], Дата = 01/02/2015 00:00:00 }"не"<>f__AnonymousType1`3[System.Collections.Generic.List`1[System.Int64],System.Collections.Generic.List`1[System.Int64],System.DateTime]"и не может использоваться на этой коллекции. Имя параметра: значение
Если я добавлю Rnd()
функция на Select
Объем, как я уже говорил, работает нормально. Проблема возникает только с анонимным объектом.
2 ответа
Похоже, это проблема манипулирования анонимными типами и NHibernate. Я бы настоятельно рекомендовал вернуть простой набор результатов, материализовать набор результатов с помощью ToList(), а затем выполнить проекции для этого набора результатов.
var employeeTeam = Session.Query<EmployeeTeam>()
.Select(x => x)
.Where(x => x.Id != 0)
.ToList();
var projectedTeam = employeeTeam.Select(x => new {x.Id});
Я не думаю, что провайдер Nhib LINQ поддерживает эту проекцию как часть отложенного выполнения. Я думаю, что вы должны поставить свою проекцию после ToList()
var employeeTeam = Session.Query<EmployeeTeam>()
.Where(x => x.StartEffective <= competency.FinalDate && // competency.FinalDate is a DateTime
employeesIds.Contains(x.EmployeeId)) // employeeIds is a List<long>
.OrderByDescending(x => x.StartEffective)
.ToList()
.Select(x => new
{
x.EmployeeId,
x.StartEffective,
x.Team
});