如何在EF Core中只包含相关表的最新记录

3

我正在使用 .net core 3.1 构建一个应用程序。我想显示一个资产列表,包括每个资产最后一次视觉检查和全面PAT测试的日期。

我正在使用以下表格/模型:

  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表,但是CheckTypeID 1 = 全面测试,CheckTypeID 2 = 目视测试。

需要进行PAT的每个资产都将有两种类型的测试的多个条目,并且我需要列出每种类型的最后一次测试的日期以及相应的资产。

  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()的变体,但我就是想不出如何把它们组合起来。

我想返回一个模型,用在索引样式页面上,最好显示类似于:

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

我对 .net / ef / c# 还很陌生,所以希望能得到一些指导。我知道如何在经典 ASP 中使用 SQL 编写视图,但尝试找出 .net core 的最佳方法。

1个回答

0

如您在 ef-core 问题 此处 中所见,存在以下评论

历史上,EF 不支持此功能,但这将是一个很好的功能。我们不得不在我们的代码库中使用 Linq 树重写实现类似的东西。希望 EF 团队考虑一下。

因此,您唯一的解决方案是转到 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预览版预览版公告

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

唯一的解决方法是编写原始SQL,但在许多情况下,您几乎需要为所有查询使用它,因此这不是一个选项,否则为什么要使用ORM。


1
谢谢您的指引,非常有帮助!我已经选择了EF 5预览版,现在可以使用.Include(c => c.PAT .Where(p => p.CheckTypeID == 1).OrderByDescending(p => p.CheckDate).Take(1))这一行代码,效果很好。关于尝试使用两个不同过滤器(一个是CheckTypeID = 1,另一个是CheckTypeID = 2)来包含PAT,您知道是否有一种别名包含的机制吗? - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接