【问题标题】:How do I include the latest record only of a related table in EF Core如何在 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 核心制定最佳方法

【问题讨论】:

    标签: c# entity-framework asp.net-core razor-pages asp.net-core-3.1


    【解决方案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 =&gt; c.PAT .Where(p =&gt; p.CheckTypeID == 1).OrderByDescending(p =&gt; p.CheckDate).Take(1)) 行,效果很好。关于尝试使用两个不同的过滤器两次包含 PAT(一个 CheckTypeID = 1 和一个 where = 2),是否有一种别名机制,包括我建议的方式你知道吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    • 2019-06-27
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多