无法创建类型为“匿名类型”的常量值。在此上下文中,只支持基元类型或枚举类型。

9

我对linq和entity framework非常陌生。 我正在尝试解决以下问题,即为什么下面的代码不起作用。生成的错误是"无法创建类型为'匿名类型'的常量值。 在此上下文中仅支持基元类型或枚举类型。"。

我已经以多种方式尝试了这个问题,但仍然遇到与基元类型相关的错误。如果有人能够查看下面的代码并指出它哪里出错,我将不胜感激。

        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()时,它会为我提供有效的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();

对于您的更新,我建议使用Sql Server Profiler并捕获EF实际发送到服务器的SQL。 - Scott Chamberlain
干杯,老兄。连接字符串问题有点傻。你活着就要学习 :-) - JIbber4568
1个回答

8
问题出在对details调用ToList()方法上。在EF中,如果要在查询中引用IEnumerable类型的内容,那么该IEnumerable必须是简单类型(例如int)。然而,您可以引用另一个IQueryable。因此,删除ToList()方法应该可以解决这个问题。
编辑:同样地,您应该在ctx.CompanySettings上删除ToList()方法。
这样做还有一个额外的好处,即只执行1个查询而不是2个。如果您在details上删除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);

谢谢你的回复。这样做的原因是我们需要跨上下文进行连接。据我所知,如果没有 .ToList(),我们将无法查询跨上下文。是否有其他方法可以允许跨上下文连接? - JIbber4568
要加入跨上下文,您需要将整个公司设置表提取到内存中,并使用 WHERE IN() 进行过滤(在 EF 中为 Contains)。 - ChaseMedallion
谢谢你对此的帮助。我采用了稍微不同的方法,但现在遇到了实体框架从数据库继承结果的问题。以上更新中是否有任何明显的问题可能导致这种情况?谢谢。 - JIbber4568

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接