调用Any或Count后,Entity Framework抛出NotSupportedException异常

4

我有以下代码:

private void Import(DbSet<DBEntity> dbEntities, IEnumerable<ExcelEntity> entities, ClapEntities context)
{
    foreach (var me in entities)
    {
        try
        {
            var dbe = dbEntities.Where(IsEqualRecord(me, context));
            bool hasElement = dbe.Any(); //Line which throws the exception
        }
        catch (Exception ex)
        {
            //...
        }
    }
}

protected abstract Expression<Func<DBEntity, bool>> IsEqualRecord(ExcelEntity entity, ClapEntities context);
< p > Any() 扩展方法会抛出一个 NotSupportedException 异常:

System.Exception:无法将实体映射到数据库。Mapper:[CuttingToolImport];Rownumber:[153] ---> System.NotSupportedException:方法“First”只能用作最终查询操作。在这种情况下,请考虑使用方法“FirstOrDefault”。
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.FirstTranslator.TranslateUnary(ExpressionConverter parent, DbExpression operand, MethodCallExpression call)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.EqualsTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.BinaryTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.AggregateTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)中
在System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert()中
在System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable<code>1 forMergeOption)中
在System.Data.Entity.Core.Objects.ObjectQuery<code>1.<>c_<DisplayClassb.b>_a()中
在System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func<code>1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)中
在System.Data.Entity.Core.Objects.ObjectQuery<code>1.<>c_<DisplayClassb.b>_9()中
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func<code>1 operation)中
在System.Data.Entity.Core.Objects.ObjectQuery<code>1.GetResults(Nullable<code>1 forMergeOption)中
在System.Data.Entity.Core.Objects.ObjectQuery<code>1..GetEnumerator>b__0()中
在System.Lazy<code>1.CreateValue()中
在System.Lazy</code>1.LazyInitValue()中
在System.Data.Entity.Internal.LazyEnumerator<code>1.MoveNext()中
在System.Linq.Enumerable.Single[TSource](IEnumerable<code>1 source)中
在System.Linq.Queryable.Count[TSource](IQueryable<code>1 source)中
在CLAP.Models.Import.ImportMapping.ImportBase</code>2.Import(DbSet<code>1 dbEntities, IEnumerable<code>1 entities, ClapEntities context)中
--- 内部异常堆栈跟踪的结尾 ---

正如您所看到的,Any()扩展(或Count()扩展)使用了内部的First()扩展,这是不允许的。我不知道该如何解决这个错误。

这段代码在Entity Framework 5或6版本中已经运行了很多个月。

Microsoft SQL Server 2012 - 11.0.2100.60 (X64) Express Edition (64-bit) on
Windows NT 6.1 <X64> (Build 7601: Service Pack 1)

有人知道如何解决这个错误吗?


好的。但是我一个月来没有改变整个代码的任何内容。它在任何时候都能正常工作。 - Florian
什么变化导致了行为的破坏? - Hari
当然这很奇怪,但必须在你的IsEqualRecord方法中完成,因为Any本身总是有效的。IsEqualRecord在调用Any时被执行。 - Gert Arnold
我会尝试你的建议 @GertArnold - Florian
很抱歉,这是不可能的。我使用的导入文件自从几个月前就一直没有变化...但无论如何,它能够正常工作 :)。 - Florian
显示剩余4条评论
1个回答

5
你应该使用 .FirstOrDefault(),当数据集中没有实体时,它将返回 NULL:
bool hasElement = dbe.FirstOrDefault() != null;

你的代码可能存在一个问题,就是你使用了自定义的 IsEqualRecord 方法,该方法应仅包含可以转换为 SQL 的代码。


首先,我无法修改EntityFramework内部的代码。我不调用First()。我调用Any()或Count(),它们会调用First()。另一件事是IsEqualRecord函数可以转换为SQL。它已经被转换为SQL好几个月了。问题已在此处解决:https://dev59.com/oXXYa4cB1Zd3GeqP-Mho - Florian
1
@thefiloe 好的,也许我表达不够清楚。请使用.FirstOrDefault() != null代替.Any() - Anatolii Gabuza
1
我认为 dbe.FirstOrDefault() 会抛出相同的异常。如果能够确认这一点,那么就可以将问题归结为 IsEqualRecord - Gert Arnold
我知道这已经过时了,但我刚刚发现它.. 我通过在.any()之前添加.toList()来解决我的问题.. 希望这能帮助未来的某个人。dbContext.MyCoolTable.ToList().Any() - Timothy
1
@Timothy,你是对的,因为在调用.ToList()之后,你将使用_Linq to Objects_而不是_Linq to Entities。但是你不应该这样做。这种方法的巨大缺点是,你将加载整个数据集到内存中,然后过滤出所需的项,这在多个方面(内存利用率、性能)都是_低效_的。 - Anatolii Gabuza

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