【问题标题】:How to select a last row from Include如何从包含中选择最后一行
【发布时间】:2016-05-26 07:28:17
【问题描述】:

我正在使用 EF 7 和 MVC 5 创建 Web 应用程序。我需要从我的数据库中选择所有标题行。

这些行将使用如下类:

public class Log_Header
{
    [Key]
    public int Id { get; set; }
    public string App_Name { get; set; }
    public string App_Url { get; set; }
    public string Submitted_By { get; set; }
    public string App_Contact { get; set; }
    public string App_Description { get; set; }

    public ICollection<Log_Detail> Details { get; set; }
}

如您所见,我收藏了Log_Details

我使用的语句如下:

public IEnumerable<Log_Header> getLogHeaders()
{
     return _context.LogHeader.Include(t => t.Details).ToList();
}

现在我遇到的问题来了,我只需要来自Details 的最后一行(最大 id 行),但我找不到这样做的方法。我尝试了一些没有运气的方法,认为它看起来类似于:

_context.LogHeader.Include(t => t.Details.Last()).ToList();

我不断收到的错误是:

“System.InvalidCastException”类型的异常发生在 EntityFramework.Core.dll 但未在用户代码中处理

附加信息:无法转换类型的对象 'Remotion.Linq.Clauses.Expressions.SubQueryExpression' 键入 'System.Linq.Expressions.MemberExpression'。

如果有人有任何线索,请发表评论或回答,请记住这是使用 EF 7。

【问题讨论】:

  • Include 期望导航属性的路径,而不是实际成员。我相信你最好的选择是延迟加载必要的对象,而不是急切地加载树。
  • @DevilSuichiro 谢谢你的回复。我相信 EF 7 目前不支持延迟加载...所以这有点问题。
  • 你试过 _context.LogHeader.Include(t => t.Details.LastOrDefault()).ToList();
  • @janina 是的,我遇到了同样的错误。 Details 也总是有一个值。
  • 你看到this的例子了吗?也许你可以使用左连接@furkick

标签: c# asp.net entity-framework linq entity-framework-core


【解决方案1】:

EF 不支持仅包含 First/Last/Whatever 行。 EF 仅支持包含整个表(即它执行 JOIN)。 因此,您将始终获得Log_Header.Count() * Log_Detail().Count() 行。 这将花费您大量的性能。

最好在 2 次往返中将数据加载到数据库。 更好的是:并行和异步执行。

public async Task<IEnumerable<Log_Header>> GetHeaderWithLastDetailAsync()
{
    var headerTask = GetLogHeadersAsync();
    var detailTask = GetLastDetailByHeaderIdAsync();

    await Task.WhenAll(headerTask, detailTask).ConfigureAwait(false);

    var header = headerTask.Result;
    var detail = detailTask.Result;

    foreach(var h in header)
    {
        Log_Detail d;
        if(detail.TryGetValue(h.Id, out d)
            h.Details.Add(d);
    }
}

public async Task<IEnumerable<Log_Header>> GetLogHeadersAsync()
{
    using(var context = new MyContext())
    {
        context.Configuration.AutoDetectChangesEnabled = false;
        context.Configuration.ProxyCreationEnabled = false;
        return await context.LogHeader.ToListAsync().ConfigureAwait(false);
    }
}

public async Task<IDictionary<int, Log_Detail>> GetLastDetailByHeaderIdAsync()
{
    using(var context = new MyContext())
    {
        context.Configuration.AutoDetectChangesEnabled = false;
        context.Configuration.ProxyCreationEnabled = false;
        return await context.LogDetail.ToDictionaryAsync(d => d.HeaderId).ConfigureAwait(false);
    }
}

【讨论】:

    猜你喜欢
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 2017-06-11
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 2013-09-13
    • 2023-03-06
    相关资源
    最近更新 更多