我对linq
和实体框架非常陌生。我试图解决一个问题,为什么以下不起作用。产生的错误是“无法创建类型为'匿名类型'的常量值。在此上下文中仅支持基本类型或枚举类型。”
我尝试了这么多不同的方法但仍然得到与原始类型有关的错误。如果有人能够查看下面的代码并希望指出它出错的地方,我将不胜感激。
public Entities.BikeData[] GetBikesWithExpiredSyncDeadline(int noOfDays) {
using (OfficeEntities cxt = GetContext())
using (ReportingEntities RepCxt = GetReportingContext()) {
Data.Repository.Abstract.IBikeRepository BikeRepos = new Data.Repository.Concrete.BikeRepository();
var details = (from sd in cxt.BikeDetails
where sd.autoreminder == true
&& (sd.lastremindersent == null || sd.lastremindersent < EntityFunctions.AddDays(DateTime.UtcNow, noOfDays * -1))
&& (sd.emailaddress != null && sd.emailaddress.Trim() != "")
select new {
Serial = sd.Serial,
EmailAddress = sd.emailaddress
}).ToList();
var resLst = (from r in RepCxt.RegisteredBikes
join d in details on r.Serial equals d.Serial
join cs in cxt.CompanySettings.ToList() on r.CompanyID equals cs.CompanyID
where (!r.lastupdate.HasValue || r.lastupdate < EntityFunctions.AddDays(DateTime.UtcNow, cs.AutoNotificationFrequency * -1))
select new Entities.BikeData {
ID = r.ID,
Name = r.Ship,
Serial = r.Serial,
LastUpdate = r.lastupdate,
DaysSinceLastSync = (r.lastupdate.HasValue? EntityFunctions.DiffDays(r.lastupdate.Value, DateTime.UtcNow).Value : -1),
EmailAddress = (d.EmailAddress == null ? string.Empty : (String.IsNullOrEmpty(d.EmailAddress) ? r.ShipEmailAddress : d.EmailAddress))
});
return resLst.ToArray();
}
}
更新
我现在通过创建视图采用了不同的方法,因此我不再需要在EF中进行交叉上下文连接。我希望你能帮助解决下面问题。
当我运行objectQuery.ToTraceString()时,它为我提供了返回db中记录的有效SQL,但是EntityFramework中的resLst总是返回0.有没有明显的原因发生这种情况?
var resLst = (from ls in cxt.BikeLastUpdates
where (!ls.lastupdate.HasValue || ls.lastupdate < EntityFunctions.AddDays(DateTime.UtcNow, ls.AutoNotificationFrequency * -1))
&& (ls.autoreminder ==true)
&& (ls.lastremindersent == null || ls.lastremindersent < EntityFunctions.AddDays(DateTime.UtcNow, 3 * -1))
&& (ls.emailaddress !=null && ls.emailaddress.Trim() != "")
select new Entities.BikeData{
ID = (ls.ID ?? new Guid()),
Name = ls.Bike,
Serial = ls.Serial,
LastUpdate = ls.lastupdate,
EmailAddress = (String.IsNullOrEmpty(ls.emailaddress) ? ls.ShipEmailAddress : ls.emailaddress)
});
var objectQuery = resLst as ObjectQuery;
return resLst.ToArray();
答案 0 :(得分:7)
问题是对细节的ToList()调用。在EF中,如果IEnumerable是简单类型(例如int),则只能引用Query中的IEnumerable。但是,您可以引用另一个IQueryable。因此,删除ToList()调用应该可以使它工作。
编辑:类似地,您应该删除ctx.CompanySettings上的ToList()调用。
这将具有仅执行1个查询而不是2的额外优势。如果在详细信息上删除ToList(),EF将生成如下内容:
SELECT ...
FROM RegisteredBikes rb
JOIN (
/* this is your "details" IQueryable */
SELECT Serial, EmailAddress
FROM BikeDetails
WHERE ...
) bd
ON rb.Serial = b.Serial
JOIN CompanySettings cs
ON ...
WHERE ...
编辑:要跨上下文执行此操作,您需要将查询带入内存(例如,通过调用AsEnumerable()并在那里执行相关联接。如果连接充当过滤器,那么在SQL中发生这些连接很重要,考虑使用Contains()。例如
var serials = details.Select(d => d.Serial);
var filtered = RepCtxt.RegisteredBikes.Where(r => details.Contains(r.Serial);