我希望能够以某种方式分解以下代码:
return from e in _context.Employees
let HasWatchedAllVideos =
(
from ev in _context.EmployeeVideos
where ev.EmployeeId == e.Id && ev.EndTime.HasValue
select ev.Id
).Count() == _context.Videos.Count()
let EndTime = HasWatchedAllVideos ?
(
from ev in _context.EmployeeVideos
where ev.EmployeeId == e.Id
select ev.EndTime
).Max() : null
let StartTime =
(
from ev in _context.EmployeeVideos
where ev.EmployeeId == e.Id
select ev.StartTime
).Min()
select new EmployeeListItem
{
Id = e.Id,
FirstName = e.FirstName,
LastName = e.LastName,
Company = e.Company,
HasWatchedAllVideos = HasWatchedAllVideos,
StartTime = StartTime,
EndTime = EndTime
};
例如,我正在寻找一种分解出来的方法:
let HasWatchedAllVideos =
(
from ev in _context.EmployeeVideos
where ev.EmployeeId == e.Id && ev.EndTime.HasValue
select ev.Id
).Count() == _context.Videos.Count()
为了可重用性而单独使用一种方法,但我无法弄清楚如何去做这件事。我试过了:
private bool HasWatchedAllVideos(int employeeId)
{
return (from ev in _context.EmployeeVideos
where ev.EmployeeId == employeeId && ev.EndTime.HasValue
select ev.Id
).Count() == _context.Videos.Count();
}
这给了我最喜欢的,'LINQ to Entities无法识别方法'例外。
答案 0 :(得分:0)
这个问题可能不会有很多动作,所以我发布的相关问题帮助我找到了更好的解决方案:
refactoring LINQ IQueryable expression to remove duplicated portions of queries
以下是我解决方案特定变体的代码:
public class AdaTrainingService : ADATraining.Web.Models.IAdaTrainingService, IDisposable
{
private ADATrainingEntities _context = new ADATrainingEntities();
public IQueryable<EmployeeListItem> GetEmployeeListing()
{
return from e in _context.Employees
join evsws in EmployeeVideoAggregatesView() on e.Id equals evsws.EmployeeId
select new EmployeeListItem
{
Id = e.Id,
FirstName = e.FirstName,
LastName = e.LastName,
Company = e.Company,
HasWatchedAllVideos = evsws.HasWatchedAllVideos,
StartTime = evsws.StartTime,
EndTime = evsws.EndTime
};
}
private class EmployeeVideoSeriesWatchingStats
{
public int EmployeeId { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public bool HasWatchedAllVideos { get; set; }
}
private IQueryable<EmployeeVideoSeriesWatchingStats> EmployeeVideoAggregatesView()
{
return from ev in _context.EmployeeVideos
group ev by ev.EmployeeId into myGroup
select new EmployeeVideoSeriesWatchingStats
{
EmployeeId = myGroup.Key,
StartTime = myGroup.Min( x => x.StartTime),
EndTime = myGroup.Max( x => x.EndTime),
HasWatchedAllVideos = myGroup.Count() == _context.Videos.Count()
};
}
public void Dispose()
{
_context.Dispose();
}
}
- 更新5/13/2011 -
上面的示例执行内部联接,并且不适用于您希望包含所有员工的实例,即使EmployeeVideoAggregatesView()没有返回任何结果,因此为了允许左外部连接,我不得不稍微调整一下代码:< / p>
public IQueryable<EmployeeDetails> GetEmployeeListing()
{
return from e in _context.Employees
join evsws in EmployeeVideoAggregatesView() on e.Id equals evsws.EmployeeId into myJoin
from mj in myJoin.DefaultIfEmpty()
select new EmployeeDetails
{
Id = e.Id,
FirstName = e.FirstName,
LastName = e.LastName,
Company = e.Company,
BadgeNumber = e.BadgeNumber,
Title = e.Title,
HasWatchedAllVideos = (mj.HasWatchedAllVideos == null) ? false : mj.HasWatchedAllVideos,
StartTime = mj.StartTime,
EndTime = mj.EndTime
};
}
答案 1 :(得分:0)
// don't count every time
var totalCount = _context.Videos.Count();
from e in _context.Employees
let HasWatchedAllVideos =
totalCount ==
_context.EmployeeVideos.Count(ev => ev.EmployeeId == e.Id && ev.EndTime.HasValue)
// count just once per employee
let employeeVideos = _context.EmployeeVideos.Count(ev => ev.EmployeeId == e.Id)
let EndTime = HasWatchedAllVideos ? employeeVideos.Max() : null
let StartTime = HasWatchedAllVideos ? employeeVideos.Min() : null
select new EmployeeListItem
{
Id = e.Id,
FirstName = e.FirstName,
LastName = e.LastName,
Company = e.Company,
HasWatchedAllVideos = HasWatchedAllVideos,
StartTime = StartTime,
EndTime = EndTime
};