C# 如何通过单个数据库调用在子集合上加载筛选的子集合?

C# 如何通过单个数据库调用在子集合上加载筛选的子集合?,c#,linq,entity-framework-core,C#,Linq,Entity Framework Core,我在C项目中有一个通用实体,它有一个信号集合 public class Entity { public int Id { get; private set; } public Guid GuidId { get; private set; } private readonly List<Signal> signals = new List<Signal>(); public IEnumerable<Signal> Signals

我在C项目中有一个通用实体,它有一个信号集合

public class Entity
{
    public int Id { get; private set; }
    public Guid GuidId { get; private set; }
    private readonly List<Signal> signals = new List<Signal>();
    public IEnumerable<Signal> Signals => this.signals.AsReadOnly();
}
我希望能够加载实体的信号和经过过滤的样本子集。目前我有以下几点:

/// <param name="guidId">entity id</param>
/// <param name="from">Beginning of the sample period</param>
/// <param name="to">End of the sample period</param>
/// <returns>Populated entity</returns>
public async Task<T> GetByGuidIdWithSignalsAsync(Guid guidId, DateTime from, DateTime to)
{
    var entity = await this.DbContext.Set<T>()
        .Include(s => s.Signals)
        .SingleAsync(s => s.GuidId == guidId);

    foreach (var signal in entity.Signals)
    {
        await this.DbContext.Entry(signal)
            .Collection(s => s.Samples)
            .Query()
            .Where(s => s.TimeStamp >= from && s.TimeStamp <= to)
            .LoadAsync();
    }

    return entity;
}

不幸的是,这需要为每个信号对数据库进行多次调用。它能被压缩成一个调用吗?

我想你需要的是类似于下面的东西,如果没有确切的类结构,写这篇文章是相当困难的。但它应该给你一个起点,如果需要的话,很乐意帮助你进一步发展

var entity = await this.DbContext.Set<T>()
        .Include(s => s.Signals)
        .SingleAsync(s => s.GuidId == guidId)
        .SelectMany(entity => entity.Signals
                              .Select(signal => signal.Samples)
                              .Where(sample => sample.TimeStamp >= from && s.TimeStamp <= to);

我认为您需要的是类似于下面的内容,如果没有确切的类结构,编写这篇文章是相当困难的。但它应该给你一个起点,如果需要的话,很乐意帮助你进一步发展

var entity = await this.DbContext.Set<T>()
        .Include(s => s.Signals)
        .SingleAsync(s => s.GuidId == guidId)
        .SelectMany(entity => entity.Signals
                              .Select(signal => signal.Samples)
                              .Where(sample => sample.TimeStamp >= from && s.TimeStamp <= to);

我想如果你从样品开始,一切都会更容易。代码看起来像:

from row in _db.Samples
where row.Signal.Entity.TimeStamp == whatever
select row

我想如果你从样品开始,一切都会更容易。代码看起来像:

from row in _db.Samples
where row.Signal.Entity.TimeStamp == whatever
select row
免责声明:我是项目的所有者

EF+免费开放源码允许轻松筛选包含的实体

例如:

var entity = await this.DbContext.Set<T>()
        .IncludeFilter(s => s.Signals)
        .IncludeFilter(s => s.Signals.SelectMany(x => Samples.Where(sa => sa.TimeStamp >= from && sa.TimeStamp <= to)))
        .SingleAsync(s => s.GuidId == guidId);
免责声明:我是项目的所有者

EF+免费开放源码允许轻松筛选包含的实体

例如:

var entity = await this.DbContext.Set<T>()
        .IncludeFilter(s => s.Signals)
        .IncludeFilter(s => s.Signals.SelectMany(x => Samples.Where(sa => sa.TimeStamp >= from && sa.TimeStamp <= to)))
        .SingleAsync(s => s.GuidId == guidId);

太好了,午饭后我会把它换掉,然后告诉你,嗨@andyb952,它几乎成功了;-您的查询已收回所有样本,但没有将它们完全加载到本地缓存中。下面的答案只在一个查询中处理了一下……太好了,午饭后我会把它换掉,让你知道,嗨@andyb952,它几乎成功了;-您的查询已收回所有样本,但没有将它们完全加载到本地缓存中。下面的答案只是在一个查询中管理它…感谢Ivan的报告,页面已更新,下次重置时将可用。EF Core for version 2.x从上个月开始就受到支持。感谢Jonathon,我没有意识到IncludeFilter是开源库的一部分,我会尝试一下并对结果进行评论。感谢Ivan的报告,该页面已更新,将在下次重置时提供。2.x版的EF Core从上个月开始就得到了支持。感谢Jonathon,我没有意识到IncludeFilter是开源库的一部分,我会尝试一下并对结果进行评论。