0

下面的代码在 LINQPad 中完美运行,但是当我在 Visual Studio 中实现它时,它不会提取任何数据。当我评论let子句和循环(1 到 5)时,我得到了所有其他数据(Pin ...Notes)。有人可以让我知道如何在 C# 中实现 let 子句吗?

public List<RouteStatus> Route_AB_List(int yardId, int siteTypeId)
{
    using (var context = new COESystemContext())
    {
        var RouteList = from site in context.Sites
                           where site.YardID == yardId && site.SiteTypeID == siteTypeId && site.Season.SeasonYear == DateTime.Now.Year
                           orderby site.Community.Name ascending
                           let Cycles = site.JobCards
                                               .Where(job => job.OperationID == 1)
                                               .OrderByDescending(job => job.ClosedDate.HasValue)
                                               .ThenBy(job => job.ClosedDate)
                                               .Select(job => new { Date = job.ClosedDate })
                           select new RouteStatus
                           {
                               Pin = site.Pin,
                               Community = site.Community.Name,
                               Neighbourhood = site.Neighbourhood,
                               Address = site.StreetAddress,
                               Area = site.Area,
                               Notes = site.Notes,
                               Cycle1 = Cycles.FirstOrDefault().Date,
                               Cycle2 = Cycles.FirstOrDefault().Equals(null) ? (DateTime?)null : Cycles.Skip(1).FirstOrDefault().Date,
                               Cycle3 = Cycles.Skip(2).FirstOrDefault().Equals(null) ? (DateTime?)null : Cycles.Skip(2).FirstOrDefault().Date,
                               Cycle4 = Cycles.Skip(3).FirstOrDefault().Equals(null) ? (DateTime?)null : Cycles.Skip(3).FirstOrDefault().Date,
                               Cycle5 = Cycles.Skip(4).FirstOrDefault().Equals(null) ? (DateTime?)null : Cycles.Skip(4).FirstOrDefault().Date
                           };
        return RouteList.ToList();

    }
}
4

1 回答 1

3

在我看来,您对每个 Cycle1 到 Cycle5 执行一次选择-where-order 循环。

此外,如果 FirstOrDefault 的结果为空,您必须做一些困难的事情。

我的建议是使用更多选择来优化您的代码。

在较小的步骤中:

var selectedSitesAndCycles = dbContext.Sites

    // keep only those sites that ...
    .Where(site => site.YardID == yardId
                && site.SiteTypeID == siteTypeId
                && site.Season.SeasonYear == DateTime.Now.Year)

    // order the remaining sites in ascending order by name
    .OrderBy(site => site.Community.Name)

    // from every ordered site, get some properties and a list of 5 cycles:
    .Select(site => new
    {
        Pin = site.Pin,
        Community = site.Community.Name,
        Neighbourhood = site.Neighbourhood,
        Address = site.StreetAddress,
        Area = site.Area,
        Notes = site.Notes,

        ClosedDates = site.JobCards
            .Where(job => job.OperationID == 1)
            .OrderByDescending(job => job.ClosedDate.HasValue)
            .ThenBy(job => job.ClosedDate)
            .Select(job => Date = job.ClosedDate)
            .Take(5)
            .ToList(),
    });

请注意,查询尚未执行。我只需要5个周期。选择 ClosedDate 时,我没有使用关键字 new。因此 CycleClosedDates 是一个List<DateTime?>.

换句话说: CycleClosedDates 的每个元素都是可以为空的 DateTime。如果您选择FirstOrDefault,您将获得第一个可为空的 DateTime,它可能是 DateTime 或 null,或者如果没有足够的 CycleClosedDates,您将获得 (DateTime?)null。

让我们检查一个站点只有三个 JobCard 的情况:

JobCard[0] is closed and has ClosedDate 2020-03-10
JobCard[1] is not closed yet. ClosedDate isn (DateTime?)null
JobCard[3] is closed and has ClosedDate 2020-03-20
// There is no JobCard[4] [5]

结果是 a List<DateTime?>,长度为 3,其中元素 [1] 没有值。的结果Skip(1).FirstOrDefault()将是一个没有值的可为空的 DateTime。

好消息是Skip(4).FirstOrDefault(),即使没有 5 个 JobCard,它也将是一个没有值的可为空的 DateTime

让我们继续使用额外的 Select 来创建您的五个属性:

    .Select(site => new
    {
        Pin = site.Pin,
        Community = site.Community.Name,
        Neighbourhood = site.Neighbourhood,
        Address = site.StreetAddress,
        Area = site.Area,
        Notes = site.Notes,

        Cycle1 = site.CycleClosedDates.FirstOrDefault(),
        Cycle2 = site.CycleClosedDates.Skip(1).FirstOrDefault(),
        Cycle3 = site.CycleClosedDates.Skip(2).FirstOrDefault(),
        ...
    })

请注意,CycleClosedDates 只会订购一次。因为 CycleClosedDates 已经是一个List<DateTime?>,所以创建单独的属性而不是一个长度为 5 的列表似乎有点多余。在您的第二个选择中考虑

.Select(site => new
{
    Pin = site.Pin,
    Community = site.Community.Name,
    ...

    CycleClosedDates = new List[]
    {
        site.CycleClosedDates.FirstOrDefault(),
        site.CycleClosedDates.Skip(1).FirstOrDefault(),
        site.CycleClosedDates.Skip(2).FirstOrDefault(),
        ...
    },
};

或者在第一次选择之后:

// move the selected data to local process
.AsEnumerable()
// 2nd select:
    .Select(site => new
{
    Pin = site.Pin,
    Community = site.Community.Name,
    ...

    CycleClosedDates = site.CycleClosedDates
        .Concat(Enumerable.Repeat( (DateTime?)null, 5)
        .Take(5)
        .ToList();

这样您就可以确定您的 CycleClosedDates 恰好有五个可为空的 DateTime,即使根本没有 JobCard。

于 2020-05-05T09:52:31.190 回答