如何在 EF Core 中仅包含相关 table 的最新记录

How do I include the latest record only of a related table in EF Core

我正在 .net core 3.1 中构建应用程序。我想显示资产列表以及每个资产进行视觉和完整拍打测试的最后日期。

我使用的tables/models如下:

  public class Asset
    {
        public int AssetID { get; set; }
        public string Title { get; set; }
        public int AssetCatID { get; set; }
        public string Manufacturer { get; set; }
        public bool RequiresPAT { get; set; }

        public AssetCat AssetCat { get; set; }
        public PAT PAT { get; set; }
    }


    public class AssetCat
    {
        public int AssetCatID { get; set; }
        public string CategoryTitle { get; set; }

        public virtual ICollection<Asset> Assets { get; set; }
    }

    public class PAT
    {
        public int PATID { get; set; }
        public int AssetID { get; set; }
        public int CheckTypeID { get; set; }
        public DateTime CheckDate { get; set; }
        public string CheckedBy { get; set; }

        public Asset Asset { get; set; }
        public CheckType CheckType { get; set; }
    }

我没有在此处包含 CheckType table,但 CheckTypeID 1 = 完整测试,CheckTypeID 2 = Visal 测试

RequiresPAT 的每个资产都将有多个条目用于两种类型的测试,我需要列出资产以及每种类型的最后一次测试的日期。

  var AssetQuery = _context.Assets
    .Where(a => a.RequiresPAT)
    .Include(a => a.AssetCat)
    .Include(a => a.PAT) // needs to just include latest PAT record where CheckTypeID = 1 if it exists AS FullPAT
    .Include(a => a.PAT) // needs to just include latest PAT record where CheckTypeID = 2 if it exists AS VisualCheck
    .ToListAsync();

我已经看到在 EF 5 中稍后会在包含中使用 .Where,但目前尚不可用。我试过在 PAT 记录上使用 .OrderByDecending(p => p.CheckDate).FirstorDefault() 的变体,但我无法弄清楚如何将它们组合在一起。

我想要 return 一个在索引样式页面上使用的模型,理想情况下显示如下内容:

Model.Asset.AssetID | Model.Asset.AssetTitle | Model.Asset.AssetCat.CategoryTitle | Model.Asset.FullPat.CheckDate | Model.Asset.VisualCheck.CheckDate

我对 .net / ef / c# 还很陌生,因此不胜感激。我确切地知道如何在 SQL 中为经典 ASP 编写视图,但试图为 .net core

找出最佳方法

正如您在 ef-core issues issue-1833 here 中看到的那样,有以下评论

Historically this was not supported by EF, However this would be a nice feature to have. We had to implement something similar ourselves in the our code base using Linq tree rewriting. It hope the EF team considers this.

所以你唯一的解决方案是使用 EF-Core 5,或者做一些类似变通解决方案的事情,这在性能方面很糟糕

var story = await _context.Stories
    .Include(x => x.Paragraphs)
    .Include(x => x.User)
    .Include(x => x.Tips)
    .Include(x => x.Images)
    .Include(x => x.Comments)
    .ThenInclude(x => x.User)
    .SingleOrDefaultAsync(x => x.Id == storyId);
if (story == null)
    return null;

story.Comments = story.Comments.Where(x => !x.IsDeleted).ToList();
story.Images = story.Images.Where(x => !x.IsDeleted).ToList();
story.Paragraphs = story.Paragraphs.Where(x => !x.IsDeleted).ToList();
story.Tips = story.Tips.Where(x => !x.IsDeleted).ToList();
return story;

所以暂时解决它(如果性能不是太忙)或使用 EF Core 5 预览 preview announcement

如评论中所述,唯一可行的选择:

The only workaround is writing raw SQL but in many cases you need it for almost all of your queries, so that's not an option or else why use an ORM to begin with.