【问题标题】:Exception when using Take in Entity Framework Core 3.1.10在 Entity Framework Core 3.1.10 中使用 Take 时出现异常
【发布时间】:2021-02-27 14:31:46
【问题描述】:

这是我尝试执行的查询:

var contests = await _dbContext.Contests.Include(o => o.Winner)
                .Where(o=>o.Ended!=null)
                .Select(c => new 
                {
                    Contest = c,
                    Strings = _dbContext.ContestCountryStrings.Where(o=>o.ContestId==c.Id && (o.Country.Equals(language) || o.Country.Equals("Default"))).ToList()
                }).Take(3).ToListAsync();

这些是实体:

[Table("Contests")]
public class Contest
{
    public int Id { get; set; }
    
    public DateTime DueTo { get; set; }
    
    public uint DurationInHours { get; set; }
    public DateTime? Started { get; set; }
    public DateTime? Ended { get; set; }
    
    public int? WinnerId { get; set; }
    public User Winner { get; set; }
    
    public bool Recurrent { get; set; }
    public string ImageUrl { get; set; }
}

[Table("ContestCountryStrings")]
public class ContestCountryString
{
    public int Id { get; set; }
    public int ContestId { get; set; }
    public Contest Contest { get; set; }
    public string Country { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
}

执行时出现如下异常:

失败: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] 执行请求时发生未处理的异常。 System.InvalidOperationException:EF.Property 调用错误 属性名称。在 Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression 方法调用表达式)在 System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor 访客)在 System.Linq.Expressions.ExpressionVisitor.Visit(表达式节点)在 Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitBinary(BinaryExpression 二进制表达式)在 Pomelo.EntityFrameworkCore.MySql.Query.ExpressionVisitors.Internal.MySqlSqlTranslatingExpressionVisitor.VisitBinary(BinaryExpression 二进制表达式)在 System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor 访客)在 System.Linq.Expressions.ExpressionVisitor.Visit(表达式节点)在 Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.Translate(表达式 表达式)在 Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateExpression(表达式 表达式)在 Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.CreateJoinPredicate(表达式 外键,表达式内键)在 Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.CreateJoinPredicate(ShapedQueryExpression 外部,LambdaExpression 外部键选择器,ShapedQueryExpression 内部, LambdaExpression innerKeySelector) 在 Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateLeftJoin(ShapedQueryExpression 外,ShapedQueryExpression 内,LambdaExpression 外键选择器, LambdaExpression innerKeySelector, LambdaExpression resultSelector)
在 Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression 方法调用表达式)在 Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression 方法调用表达式)在 System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor 访客)在 System.Linq.Expressions.ExpressionVisitor.Visit(表达式节点)在 Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression 方法调用表达式)在 Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression 方法调用表达式)在 System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor 访客)在 System.Linq.Expressions.ExpressionVisitor.Visit(表达式节点)在 Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](表达式 查询)在 Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](表达式 查询,布尔异步)在 Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase 数据库、表达式查询、IModel 模型、布尔异步)在 Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.c__DisplayClass12_01.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func1 编译器)在 Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](对象 cacheKey, Func1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1.GetAsyncEnumerator(CancellationToken 取消令牌)在 System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable1.GetAsyncEnumerator() at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable1 来源,CancellationToken 取消令牌)在 MoneyAppBackend.Controllers.ContestsController._GetLas10PastEvents(EventType 类型,字符串语言)在 /Users/juanjoseduran/Documents/Development/Projects/dotnet/MoneyAppBackend/MoneyAppBackend/Controllers/ContestsController.cs:line 106 在 MoneyAppBackend.Controllers.ContestsController.GetAll(EventType 类型, 字符串 lang,字符串 uuid)在 /Users/juanjoseduran/Documents/Development/Projects/dotnet/MoneyAppBackend/MoneyAppBackend/Controllers/ContestsController.cs:line 57 at lambda_method(Closure, Object) at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult() 在 Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper 映射器,ObjectMethodExecutor 执行器,对象控制器,Object[] 论据)在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker 调用者,ValueTask`1 actionResultValueTask) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker 调用者,任务 lastTask,下一个状态,作用域范围,对象状态,布尔值 已完成)在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed 上下文)在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(状态& next, Scope& 范围, Object& 状态, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker 调用者,任务 lastTask,下一个状态,作用域范围,对象状态,布尔值 已完成)在 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker 调用者、任务任务、IDisposable 范围)在 Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(端点 端点,任务 requestTask,ILogger 记录器)在 Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext 上下文)在 Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文)

如果我删除 Take 呼叫,它会正常工作。

【问题讨论】:

  • 如果将Take 移到Select 之前会发生什么?

标签: linq asp.net-core linq-to-sql entity-framework-core pomelo-entityframeworkcore-mysql


【解决方案1】:

就像@NetMage说的,既然你要take的数据是Contest类型的数据,如果你把take放在Select后面就是对Select后面的数据进行操作,数据获取的不会是Contest类型,会导致异常。

您可以像下面这样更改您的代码:

var contests = await _dbContext.Contests.Include(o => o.Winner)
        .Where(o=>o.Ended!=null).Take(3)
        .Select(c => new 
        {
            Contest = c,
            Strings = _dbContext.ContestCountryStrings.Where(o=>o.ContestId==c.Id && (o.Country.Equals(language) || o.Country.Equals("Default"))).ToList()
        }).ToListAsync();

【讨论】:

  • 这两个版本不会获取所有行然后应用过滤器吗?这正是我在查询中试图避免的。感谢您提供的示例,但我想在查询中将行的获取保持在最低限度。
  • 如果 Take() 是匿名类型,为什么会有问题?您可以对匿名类型执行 Take(3),不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多