2016-01-29 2 views
21

У меня есть простой запрос, как показано ниже: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(); 

Он успешно работает один раз, но при выполнении во второй раз (или третий, четвертый и так сын) он бросает недействительный литая исключение, как:

Fatal Error:System.InvalidCastException: Cannot convert type 'System.Linq.EnumerableQuery`1[<>f__AnonymousType0`3[System.Int64,System.DateTime,Team]]' to 'System.Collections.Generic.IEnumerable`1[<>f__AnonymousType0`3[System.Int64,System.DateTime,Team]]'. in NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)

Остальной трассировки стека подавлено для bravety.

Запрос всегда выполняется в базе данных до ошибки. Он не возвращает никаких записей, но это нормально. Если я перестрою решение и снова запустится, запрос будет выполнен в первый раз снова, а затем начнет бросать исключение друг за другом, когда я его запустил. Другие запросы запускаются каждый раз без каких-либо проблем. Я не знаю, что вызывает ошибку.

Важно сказать, что этот код работает в среде CSharpCodeProvider, но я не знаю, может ли это изменить ситуацию.

UPDATE

Это происходит даже с самой простой формой запроса:

var employeeTeam = Session.Query<EmployeeTeam>() 
         .Select(x => new 
         { 
          x.Id 
         }).ToList(); 

Он работает нормально только в первый раз. Но если я изменяю объект annon от { x.Id } до { x.TeamId }, например, он запускается нормально в первый раз, тогда исключения повторяются снова.

UPDATE 2

Я просто понимаю, что если я добавлю следующее свойство объекта Annon, запрос работает каждый раз:

Rnd = (new Random().Next(1, 999)) 

Таким образом, вопрос кэша может быть?

UPDATE 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: The value "{ HoliDayCities = System.Collections.Generic.List`1[System.Int64], HoliDayStates = System.Collections.Generic.List`1[System.Int64], Date = 01/02/2015 00:00:00 }" is not "<>f__AnonymousType1`3[System.Collections.Generic.List`1[System.Int64],System.Collections.Generic.List`1[System.Int64],System.DateTime]" and cannot be used on this collection. Parameter name: value

Если я добавьте функцию Rnd() на Select scope как я упоминал ранее, он отлично работает. Проблема возникает только с анонимным объектом.

UPDATE 4

Я создал пример проекта для имитации проблемы. Это не совсем та же структура, но исключение довольно похоже. Он находится на этом репо: https://github.com/felipeoriani/nh-bug

Код ошибки to nhibernate создавать новые таблицы в базе данных.

+0

Что произойдет, если вы переместите 'OrderByDescending (x => x.StartEffective)' вправо после проекции? –

+0

@GertArnold Это не изменяет результат. Даже удаление 'OrderByDescending' проблемы остается. – DontVoteMeDown

+0

@GertArnold Я добавил новую информацию. – DontVoteMeDown

ответ

-2

Я не думаю, что поставщик 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 
        }); 
+0

Благодарим вас за ответ. Он не меняет результат. Я даже удалил метод 'OrderByDescending', но проблема остается. – DontVoteMeDown

+0

Я добавил новую информацию – DontVoteMeDown

+0

, которую вы можете проецировать в анонимный или названный объект. Использование проекции гарантирует, что запрос, который генерируется, имеет только значения, необходимые для извлечения. – Fran

1

Похоже, что это проблема с манипулируя анонимные типы и NHibernate. Я бы предложил предложить простой набор результатов, материализуя набор результатов с помощью ToList(), а затем выполнив прогнозы на этом наборе результатов.

var employeeTeam = Session.Query<EmployeeTeam>() 
          .Select(x => x) 
          .Where(x => x.Id != 0) 
          .ToList(); 

var projectedTeam = employeeTeam.Select(x => new {x.Id}); 
+0

Благодарим вас за ответ. Это прекрасно работает. Но у меня все еще есть проблема, я постараюсь ее решить. Его важно выяснить, потому что это может произойти где-то еще в ближайшем будущем в моем приложении. – DontVoteMeDown