Метод Last () не работает с объектом IQueryable - PullRequest
1 голос
/ 13 августа 2010

Я все еще новичок в C #, поэтому, возможно, я делаю что-то глупое, но я потратил некоторое время на это и все еще не понимаю, в чем проблема.

Вот некоторые фрагменты кода:

        double work = 0;
        ProjectRepository pr = new ProjectRepository();
        IQueryable<CalendarDetail> cds;

        // Find matching day of week
        // Then for that day, cycle through all working times

        // Return list of working times in day
        cds = pr.GetCalDetails(calendarID, startTime.DayOfWeek.GetHashCode());

        foreach (CalendarDetail cd in cds)
        {
            DateTime wts = startTime.Date + cd.WorkingTimeStart.Value.TimeOfDay;
            DateTime wtf = startTime.Date + cd.WorkingTimeFinish.Value.TimeOfDay;

            //more code here....

           if ((cds.Last().CalendarDetailID == cd.CalendarDetailID) && (finishTime > wtf))
                work += Work(startTime.Date.AddDays(1), finishTime, calendarID);
         }

Ошибка генерируется во время выполнения из-за моего использования вызова метода cds.Last (). Тем не менее, cds был объявлен и используется как объект IQueryable, так в чем же проблема?

Текст ошибки: Оператор запроса «Последний» не поддерживается.

Если решение не найдено, я уверен, что смогу «логически» обойти эту проблему, но это показалось изящным.

Спасибо

Jonathan

Ответы [ 6 ]

4 голосов
/ 04 февраля 2015

Ответ заключается в том, что не все поставщики IQueryable поддерживают все методы Linq.Поставщики IQeuryable с бэкэндом SQL, такие как LinqToSql или Entity Framework, не поддерживают Last (), потому что сам SQL не имеет концепции Last.Нет оператора SQL для перевода Last () в.

В SQL правильный подход - правильно упорядочить записи (возможно, по Id Desc), а затем выполнить Top 1. Так вот, что нам нужноделать в Линк:

CalendarDetail lastCd = cds.OrderByDescending(cd => cd.CalendarDetailId).First();
2 голосов
/ 19 ноября 2012

Похоже, что Linq не поддерживает Last() в IQueryable. Вы можете сделать это:

List<CalendarDetail> cds;

    // Find matching day of week
    // Then for that day, cycle through all working times

    // Return list of working times in day
    cds = pr.GetCalDetails(calendarID, startTime.DayOfWeek.GetHashCode()).ToList();
2 голосов
/ 13 августа 2010

Я не думаю, что в этом вопросе достаточно подробностей, чтобы ответить на него, потому что вы не указываете, каким на самом деле было исключение.

Возможно, стоит заменить вызов .Last () на.AsEnumerable (). Last (), так как это будет указывать на то, была ли проблема вообще с Last () или если это было в другом месте в запросе.не может быть быстрее, поэтому обычно не стоит этого делать, если вы можете избежать этого, но (A) может быть, вы не можете этого сделать из-за некоторых ограничений в поставщике запросов и (B) в результате попытки попробовать и посмотреть, получите ли вы то же самоеИсключение расскажет вам больше о вашей проблеме.

1 голос
/ 13 августа 2010

Вы должны сообщить нам, что это ошибка / исключение, чтобы помочь должным образом, но наиболее распространенная причина сбоя Last () - это то, что провайдер IQeryable не поддерживает его.например, я не думаю, что LinqToSQL поддерживает Last ()

1 голос
/ 13 августа 2010

Трудно угадать причину, не зная исключение, которое вы бросили но вы можете сделать все это в linq, так что я подумал, что это может быть ценной информацией для вас

var lastID = cds.Last().CalendarDetailID;
var work =  (from cd in cds
            let wts = startTime.Date + cd.WorkingTimeStart.Value.TimeOfDay
            let wtf = startTime.Date + cd.WorkingTimeFinish.Value.TimeOfDay
            where (lastID == cd.CalendarDetailID) && (finishTime > wtf)
            select Work(startTime.Date.AddDays(1), finishTime, calendarID)).Sum();

(при условии, что работа может быть неявно преобразована во что-то, что может обработать .Sum (). То есть + = не является пользовательским оператором)

0 голосов
/ 01 июня 2016

если ваш CalendarDetailID работает с цифрой, вы можете использовать Max ()

...