无法创建类型的常量值在此上下文中仅支持原始类型或枚举类型


164

我在下面的查询中遇到此错误

无法创建类型的常量值API.Models.PersonProtocol。在此上下文中仅支持原始类型或枚举类型

ppCombined下面是的IEnumerable对象PersonProtocolType,由2个PersonProtocol列表的concat构造。

为什么会失败?我们不能JOINSELECTa 内部使用LINQ 子句JOIN吗?

var persons = db.Favorites
    .Where(x => x.userId == userId)
    .Join(db.Person, x => x.personId, y => y.personId, (x, y) =>
        new PersonDTO
        {
            personId = y.personId,
            addressId = y.addressId,                   
            favoriteId = x.favoriteId,
            personProtocol = (ICollection<PersonProtocol>) ppCombined
                .Where(a => a.personId == x.personId)
                .Select( b => new PersonProtocol()
                 {
                     personProtocolId = b.personProtocolId,
                     activateDt = b.activateDt,
                     personId = b.personId
                 })
        });


Answers:


232

ppCombined是行不通的,因为它是内存中的一组对象,并且您无法将数据库中的一组数据与内存中的另一组数据连接在一起。你可以尝试,而不是提取经过滤项personProtocol中的ppCombined集合中的内存后,您检索从数据库中其他属性:

var persons = db.Favorites
    .Where(f => f.userId == userId)
    .Join(db.Person, f => f.personId, p => p.personId, (f, p) =>
        new // anonymous object
        {
            personId = p.personId,
            addressId = p.addressId,   
            favoriteId = f.favoriteId,
        })
    .AsEnumerable() // database query ends here, the rest is a query in memory
    .Select(x =>
        new PersonDTO
        {
            personId = x.personId,
            addressId = x.addressId,   
            favoriteId = x.favoriteId,
            personProtocol = ppCombined
                .Where(p => p.personId == x.personId)
                .Select(p => new PersonProtocol
                {
                    personProtocolId = p.personProtocolId,
                    activateDt = p.activateDt,
                    personId = p.personId
                })
                .ToList()
        });

10
对我来说,关键部分是添加.AsEnumerable()//数据库查询到此结束,其余的是内存中的查询
Sameer Alibhai 2015年

2
@Slauma因此,如果我担心性能,应该避免这样做,因为它将首先加载内存中的所有数据,然后再查询它。我应该为这种情况编写原始sql吗?
2015年

好像@Arvand有一个优点。如果过滤器之前有大量记录,则可能会占用大量可用内存资源。
spadelives's

5
@Slauma“这无法工作,因为ppCombined是内存中的对象的集合,并且您无法将数据库中的一组数据与内存中的另一组数据连接在一起。” 在哪里可以找到有关此类文件的文档?我真的很缺乏EF限制的知识,当我尝试限制这样的查询结果集时,这种无能使自己变得非常明显,并使我放慢了速度。
命名者

1
好信息。我将此例外添加到我的最不直观的例外消息列表中。只有在您了解其发生原因之后,才有意义。
DVK

2

不知道是否有人搜索。我有同样的问题。在查询中进行选择,然后执行where(或联接)并使用select变量为我解决了这个问题。(问题出在我的“重新整合”集合中)

query.Select(zv => new
            {
                zv,
                rId = zv.this.Reintegraties.FirstOrDefault().Id
            })
            .Where(x => !db.Taken.Any(t => t.HoortBijEntiteitId == x.rId
                                             && t.HoortBijEntiteitType == EntiteitType.Reintegratie
                                             && t.Type == TaakType))
            .Select(x => x.zv);

希望这对任何人有帮助。


6
zv.this.Reintegraties.FirstOrDefault().Id潜在的NullReferenceException

2

就我而言,我可以通过执行以下操作解决此问题:

我从这里更改了代码:

var r2 = db.Instances.Where(x => x.Player1 == inputViewModel.InstanceList.FirstOrDefault().Player2 && x.Player2 == inputViewModel.InstanceList.FirstOrDefault().Player1).ToList();

对此:

var p1 = inputViewModel.InstanceList.FirstOrDefault().Player1;
var p2 = inputViewModel.InstanceList.FirstOrDefault().Player2;
var r1 = db.Instances.Where(x => x.Player1 == p1 && x.Player2 == p2).ToList();

这对我不起作用。作为p1p2在内存都是它们是否匿名声明或变量名。
Rahat Zaman

2
变量类型不是问题。在我的情况下,错误是由于在Where子句中执行了.FirstOrDefault()而引起的。
科林

2

值得添加,因为OP的代码示例没有提供足够的上下文来证明否则,但是我在以下代码上也收到此错误:

public RetailSale GetByRefersToRetailSaleId(Int32 refersToRetailSaleId)
{
    return GetQueryable()
        .FirstOrDefault(x => x.RefersToRetailSaleId.Equals(refersToRetailSaleId));
}

显然,Int32.Equals在这种情况下,我无法使用Int32与原始int进行比较。我不得不(安全地)更改为:

public RetailSale GetByRefersToRetailSaleId(Int32 refersToRetailSaleId)
{
    return GetQueryable()
      .FirstOrDefault(x => x.RefersToRetailSaleId == refersToRetailSaleId);
}

EF接受得Equals很好。
Gert Arnold

0

只需添加AsEnumerable()和ToList(),它看起来像这样

db.Favorites
    .Where(x => x.userId == userId)
    .Join(db.Person, x => x.personId, y => y.personId, (x, y).ToList().AsEnumerable()

ToList().AsEnumerable()

0

我遇到了这个问题,而我所解决的问题是我AsEnumerable()在Join子句之前使用了该问题。这是我的查询:

List<AccountViewModel> selectedAccounts;

 using (ctx = SmallContext.GetInstance()) {
                var data = ctx.Transactions.
                    Include(x => x.Source).
                    Include(x => x.Relation).
                    AsEnumerable().
                    Join(selectedAccounts, x => x.Source.Id, y => y.Id, (x, y) => x).
                    GroupBy(x => new { Id = x.Relation.Id, Name = x.Relation.Name }).
                    ToList();
            }

我想知道为什么会发生此问题,现在我想这是因为通过LINQ进行查询后,结果将在内存中而不是加载到对象中,我不知道该状态是什么,但是它们处于某些状态我认为是过渡状态。然后,当您使用AsEnumerable()或时ToList(),将它们放入物理内存对象中即可解决问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.