无法创建类型为“匿名类型”的常量值。在此上下文中仅支持基本类型或枚举类型 [英] Unable to create a constant value of type 'Anonymous type'. Only primitive types or enumeration types are supported in this context

查看:2904
本文介绍了无法创建类型为“匿名类型”的常量值。在此上下文中仅支持基本类型或枚举类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对于 linq 和实体框架非常新鲜。我试图解决一个问题,为什么下面的工作不起作用。产生的错误是无法创建类型Anonymous type的常量值,在此上下文中仅支持基本类型或枚举类型。

I am extremely new to linq and entity framework. I am trying to resolve a problem as to why the below isn't working. The error produced is "Unable to create a constant value of type 'Anonymous type'. Only primitive types or enumeration types are supported in this context."

这么多不同的方法仍然会得到与原始类型相关的错误。如果有人可以看下面的代码,希望能指出出错的地方,我会非常感激。

I've tried this so many different ways yet still get an error relating to primitive types. I would greatly appreciate it if someone could take a look at the below code and hopefully point out where it's going wrong.

        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中进行交叉上下文连接。我希望你可以帮助下面。

I've taken a different approach with this now by creating a view so I no longer need to do the cross context joins in EF. I was hoping you may be able to help with the below.

当我运行objectQuery.ToTraceString()时,它为我提供了返回数据库中记录的有效SQL EntityFramework中的resLst总是返回0.对于为什么会发生这种情况有什么明显的吗?

When I run objectQuery.ToTraceString() it provides me with valid SQL that returns records in the db, however the resLst in EntityFramework always comes back with 0. Is there anything obvious as to why this is happening?

  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();


推荐答案

问题是ToList()调用详细信息。在EF中,如果该IEnumerable是一个简单的类型(例如int),则只能在查询内引用IEnumerable。但是,您可以参考另一个IQueryable。因此,删除ToList()调用应该使这个工作。

The problem is the ToList() call on details. In EF, you can only refer to an IEnumerable inside a Query if that IEnumerable is of a simple type (e. g. int). However, you CAN refer to another IQueryable. Thus, dropping the ToList() call should make this work.

编辑:同样,你应该删除ctx.CompanySettings上的ToList()调用。

similarly, you should drop the ToList() call on ctx.CompanySettings.

这将具有仅执行1个查询而不是2的附加优势。如果您放弃ToList()的详细信息,EF将生成如下内容:

This will have the added advantage of executing only 1 query instead of 2. If you drop the ToList() on details, EF will generate something like:

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(),例如

to do this across contexts, you'll need to bring the query into memory (e. g. by calling AsEnumerable() and do the relevant joins there. If the joins act as filters and it's important for these to happen in SQL, consider using Contains(). For example

var serials = details.Select(d => d.Serial);
var filtered = RepCtxt.RegisteredBikes.Where(r => details.Contains(r.Serial);

这篇关于无法创建类型为“匿名类型”的常量值。在此上下文中仅支持基本类型或枚举类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆