C# 如何从包含中选择最后一行
我正在使用EF7和MVC5创建一个web应用程序。我需要从数据库中选择所有标题行 这些行将使用如下所示的类:C# 如何从包含中选择最后一行,c#,asp.net,entity-framework,linq,entity-framework-core,C#,Asp.net,Entity Framework,Linq,Entity Framework Core,我正在使用EF7和MVC5创建一个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 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; }
}
现在我遇到了一个问题,我只需要Details
中的最后一行(max-id行),但我找不到一种方法。我尝试过几种方法,但都不走运,我想它看起来会像这样:
_context.LogHeader.Include(t => t.Details.Last()).ToList();
我经常遇到的错误是:
中发生“System.InvalidCastException”类型的异常
EntityFramework.Core.dll,但未在用户代码中处理
其他信息:无法强制转换类型为的对象
“Remotion.Linq.子句.Expressions.SubQueryExpression”以键入
'System.Linq.Expressions.MemberExpression'
如果任何人有任何线索,请留下评论或回答,请记住这是使用EF 7。EF不支持只包含第一行/最后一行/任何行。 EF仅支持包含整个表(即,它进行连接)。 因此,您将始终获得
Log\u Header.Count()*Log\u Detail().Count()
行。
这将花费您大量的性能
最好通过两次往返将数据加载到数据库。
更好的是:以并行和异步方式进行
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);
}
}
公共异步任务GetHeaderWithLastDetailAsync()
{
var headerTask=getLogHeaderAsync();
var detailTask=GetLastDetailByHeaderIdAsync();
wait Task.WhenAll(headerTask,detailTask).configurewait(false);
var header=headerTask.Result;
var detail=detailTask.Result;
foreach(表头中的var h)
{
日志详细信息d;
if(详细信息TryGetValue(h.Id,out d)
h、 详情.添加(d);
}
}
公共异步任务getLogHeaderAsync()
{
使用(var context=new MyContext())
{
context.Configuration.AutoDetectChangesEnabled=false;
context.Configuration.ProxyCreationEnabled=false;
返回wait context.LogHeader.ToListAsync().configurewait(false);
}
}
公共异步任务GetLastDetailByHeaderIdAsync()
{
使用(var context=new MyContext())
{
context.Configuration.AutoDetectChangesEnabled=false;
context.Configuration.ProxyCreationEnabled=false;
返回wait context.LogDetail.ToDictionaryAsync(d=>d.HeaderId).configurewait(false);
}
}
Include需要导航属性的路径,而不是实际的成员。我相信您最好的选择是延迟加载所需的对象,而不是急切地加载树。@DevilSuichiro感谢您的回复。我相信EF 7目前不支持延迟加载…所以这有点问题。您是否尝试过\u context.LogHeader.Includee(t=>t.Details.LastOrDefault()).ToList();@janina是的,我得到了相同的错误。而且
Details
将始终有一个值。您看到示例了吗?也许您可以使用left join@furchick
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);
}
}