Last()方法不适用于IQueryable对象

时间:2010-08-13 11:22:04

标签: c# iqueryable

我还很新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对象,那么问题是什么?

错误文字:

不支持查询运算符“Last”

失败的解决方案我确信我可以“逻辑”解决问题,但这似乎很优雅。

谢谢,

乔纳森

6 个答案:

答案 0 :(得分:4)

答案是并非所有IQueryable提供程序都支持所有Linq方法。具有SQL后端的IQeuryable提供程序(如LinqToSql或Entity Framework)不支持Last(),因为SQL本身并不具有Last的概念。 Last()没有SQL语句要翻译成。

在SQL中,正确的方法是适当地对记录进行排序(或许通过Id Desc),然后进行Top 1.这就是我们在Linq中需要做的事情:

CalendarDetail lastCd = cds.OrderByDescending(cd => cd.CalendarDetailId).First();

答案 1 :(得分:2)

我不认为这个问题有足够的细节来回答它,因为你没有说明实际上是什么例外。

将.Last()的调用替换为.AsEnumerable()。Last()可能是值得的,因为这将指示问题是否与Last()完全相同,或者是否在查询的其他位置。 / p>

.AsEnumerable()。Last()可以更慢,也不能更快,所以如果你可以避免它,一般不值得做,但(A)也许你不能因为查询提供程序中的一些限制而(B)尝试它的结果,看看你是否得到相同的例外将告诉你更多关于你的问题。

答案 2 :(得分:2)

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();

答案 3 :(得分:1)

在知道你被抛出的异常时很难猜测原因 但你实际上可以在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()可以处理的东西。即+ =不是自定义运算符)

答案 4 :(得分:1)

您需要告诉我们错误/异常是如何正确帮助的,但Last()失败的最常见原因是IQeryable提供程序不支持它。例如我不认为LinqToSQL支持Last()

答案 5 :(得分:0)

如果您的CalendarDetailID正在运行数字,则可以使用Max()