我正在使用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。
答案 0 :(得分:1)
EF不支持只包含First / Last / Whatever行。
EF仅支持包括整个表(即它执行JOIN)。
因此,您将始终获得Log_Header.Count() * Log_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);
}
}