【问题标题】:Unable to create a constant value of type Only primitive types or enumeration types are supported in this context无法创建类型的常量值 此上下文仅支持原始类型或枚举类型
【发布时间】:2013-09-26 14:12:51
【问题描述】:

以下查询出现此错误

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

下面的ppCombinedPersonProtocolType的一个IEnumerable对象,由2个PersonProtocol列表的concat构成。

为什么会失败?我们不能在JOINSELECT 内使用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
                 })
        });

【问题讨论】:

标签: c# linq entity-framework join


【解决方案1】:

这不起作用,因为ppCombined 是内存中对象的集合,您不能将数据库中的一组数据与内存中的另一组数据连接起来。您可以尝试在您从数据库中检索其他属性之后提取内存中ppCombined 集合中的过滤项目personProtocol

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

【讨论】:

  • 对我来说关键部分是添加 .AsEnumerable() // 数据库查询到此结束,剩下的就是内存中的查询
  • @Slauma 因此,如果我担心性能,我应该避免这样做,因为它会先将所有数据加载到内存中,然后再进行查询。我应该为这种情况编写原始 sql 吗?
  • 看来@Arvand 有一个很好的观点。如果您在过滤器之前有大量记录,这可能会占用大量可用内存资源。
  • @Slauma “这不起作用,因为 ppCombined 是内存中对象的集合,您不能将数据库中的一组数据与内存中的另一组数据连接起来。”我在哪里可以找到有关此类事情的文档?我真的缺乏对 EF 限制的了解,当我尝试像这样限制查询的结果集时,这种无能非常明显,让我放慢了速度。
  • 很好的信息。我将此异常添加到我最不直观的异常消息列表中。只有在您了解它发生的原因之后才有意义。
【解决方案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 都在内存中,无论它们是匿名声明还是通过变量名声明。
  • 变量类型不是问题。在我的情况下,错误是由于在 Where 子句中执行 .FirstOrDefault() 引起的。
  • 这就是我的解决方案!非常感谢@Colin :)
【解决方案3】:

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

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

希望这对任何人都有帮助。

【讨论】:

  • zv.this.Reintegraties.FirstOrDefault().Id 潜在的 NullReferenceException
【解决方案4】:

值得添加,因为 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);
}

【讨论】:

    【解决方案5】:

    我遇到了这个问题,我做了什么,解决了问题是我在加入子句之前使用了AsEnumerable()。 这是我的查询:

    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() 等时,您将它们放入物理内存对象中,问题正在解决。

    【讨论】:

    • 不适合我
    【解决方案6】:

    只要加上 AsEnumerable() 和 ToList() ,就变成了这样

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多