LINQ to Entities无法识别方法'Boolean Contains[Decimal]。

4

我是LINQ的新手,所以在这里感到相当困惑。我有一个数据库并尝试运行以下代码。

IQueryable<decimal> location_ids = (from m in _db.Admins
                                    where m.UserId.Equals("c5d3dc0e-81e6-4d6b-a9c3-faa802e10b7d")
                                    select m.LocationId);
if (!location_ids.Contains(new Decimal(conf.umisteni.Budova.ID)))

在if语句中,我遇到了一个错误,我不理解它,并且也不知道如何解决它:
System.NotSupportedException: LINQ to Entities does not recognize the method 'Boolean Contains[Decimal](System.Linq.IQueryable`1[System.Decimal], System.Decimal)' method, and this method cannot be translated into a store expression.
  at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)

有什么想法吗?
4个回答

9
使用 Linq-to-Objects 的 IEnumerable,您可以在查询结果上使用 Contains(Decimal)。
IEnumerable<decimal> location_ids = (from m in _db.Admins
                                    where m.UserId.Equals("c5d3dc0e-81e6-4d6b-a9c3-faa802e10b7d")
                                    select m.LocationId);

然而,为什么不直接扩展where子句呢:
IEnumerable<decimal> location_ids = (from m in _db.Admins
                                    where m.UserId.Equals("c5d3dc0e-81e6-4d6b-a9c3-faa802e10b7d") && (m.LocationId == conf.umisteni.Budova.ID)
                                    select m.LocationId);
if (!location_ids.Any())

6
可以用 Any() 替换 .Count() == 0。 - Boris Callens

1
Linq 2 sql无法将ids.Contains()方法翻译为sql。 你可以尝试以下操作:
if(!location_ids.ToList().Contains(new Decimal(conf.umisteni.Budova.ID)))

这将触发SQL查询,将它们放入对象中并在本地执行包含操作。

另一种解决方案是将conf.umisteni.Budova.Id放入Where子句中(使用等于而不是包含),然后添加.any。

if((from m in _db.Admins
    where m.UserId.Equals(conf.umisteni.Budova.ID.ToString())
    select m.LocationId).Any())

当然,如果之后不需要任何键,则这只是一个好主意。


你的第二个建议将UserID与conf.umisteni.Budova.ID进行了比较,而应该是LocationId。 - Yannick Motton
当然。不过想法保持不变。 - Boris Callens

1
这是一个辅助方法,它在Linq to Entities的上下文中提供了.Contains()的所有好处。
public static class LinqToEntitiesUtil
{
    /// <summary>
    /// Extension method that enables .Contains(obj) like functionality for Linq to Entities.
    /// 
    /// Source: http://www.velocityreviews.com/forums/t645784-linq-where-clause.html
    /// </summary>
    /// <typeparam name="TElement">The element being evaluated by the Where clause</typeparam>
    /// <typeparam name="TValue">The value to match</typeparam>
    /// <param name="valueSelector">Lamda for selecting matching values</param>
    /// <param name="values">IEnumerable of the values</param>
    /// <returns>Expression consumable by Linq to Entities that reflects semantics of .Contains(value)</returns>
    /// <remarks>
    /// Usage:
    /// 
    /// Replace expression like 
    /// 
    /// where ChildrenIDs.Contains(items.CategoryID)
    /// 
    /// with
    /// 
    /// .Where((BuildContainsExpression<Item, int>(item => item.CategoryID, ChildrenIDs))
    /// 
    /// NOTE: If the item collection is large, the SQL query will be as well.
    /// </remarks>
    static public Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
    {
        if (null == valueSelector)
        {
            throw new ArgumentNullException("valueSelector");
        }
        if (null == values) { throw new ArgumentNullException("values"); }

        ParameterExpression p = valueSelector.Parameters.Single();
        if (!values.Any())
        {
            return e => false;
        }

        var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
        var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));
        return Expression.Lambda<Func<TElement, bool>>(body, p);
    }
}

+1 对于可行的解决方案。不禁让人想知道为什么在 Entity Framework 中这样简单的事情如此困难... - Andomar

0
我刚遇到了类似的问题。你的 System.Data.dll 可能不是同一个版本。这个方法在我的开发机上是支持的,但是当我部署到测试机器上时,就会出现运行时错误。System.Data.dll 的版本较旧。向后兼容的方法是一个好的解决方案。但我仍然想追踪这个差异,可能有一些补丁没有应用到其他环境中。如果不加以检查,谁知道这将在未来引起什么其他问题呢。

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