如何在 EF Core 中仅包含相关表的最新记录
Posted
技术标签:
【中文标题】如何在 EF Core 中仅包含相关表的最新记录【英文标题】:How do I include the latest record only of a related table in EF Core 【发布时间】:2020-08-28 02:28:01 【问题描述】:我正在 .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 = 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() 的变体,但我无法弄清楚如何将它们组合在一起。
我想返回一个模型以在索引样式页面上使用,理想情况下显示如下内容:
Model.Asset.AssetID | Model.Asset.AssetTitle | Model.Asset.AssetCat.CategoryTitle | Model.Asset.FullPat.CheckDate | Model.Asset.VisualCheck.CheckDate
我对 .net / ef / c# 很陌生,所以任何指针都将不胜感激。我确切地知道如何在 SQL 中为经典 ASP 编写视图,但试图为 .net 核心制定最佳方法
【问题讨论】:
【参考方案1】:正如您在 ef-core 问题 issue-1833 here 中看到的,有以下评论
从历史上看,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 预览版preview announcement
如 cmets 所述,唯一可行的选择:
唯一的解决方法是编写原始 SQL,但在许多情况下,几乎所有查询都需要它,所以这不是一个选项,否则为什么要使用 ORM 开始。
【讨论】:
感谢您的指导,非常有帮助!我已经使用了 EF 5 预览版,现在可以使用.Include(c => c.PAT .Where(p => p.CheckTypeID == 1).OrderByDescending(p => p.CheckDate).Take(1))
行,效果很好。关于尝试使用两个不同的过滤器两次包含 PAT(一个 CheckTypeID = 1 和一个 where = 2),是否有一种别名机制,包括我建议的方式你知道吗?以上是关于如何在 EF Core 中仅包含相关表的最新记录的主要内容,如果未能解决你的问题,请参考以下文章