使用 Take in Entity Framework Core 3.1.10 时出现异常
Exception when using Take in Entity Framework Core 3.1.10
这是我尝试执行的查询:
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; }
}
执行时出现如下异常:
fail:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request. System.InvalidOperationException: EF.Property called with wrong
property name. at
Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression
methodCallExpression) at
System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor
visitor) at
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at
Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitBinary(BinaryExpression
binaryExpression) at
Pomelo.EntityFrameworkCore.MySql.Query.ExpressionVisitors.Internal.MySqlSqlTranslatingExpressionVisitor.VisitBinary(BinaryExpression
binaryExpression) at
System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor
visitor) at
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at
Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.Translate(Expression
expression) at
Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateExpression(Expression
expression) at
Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.CreateJoinPredicate(Expression
outerKey, Expression innerKey) at
Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.CreateJoinPredicate(ShapedQueryExpression
outer, LambdaExpression outerKeySelector, ShapedQueryExpression inner,
LambdaExpression innerKeySelector) at
Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateLeftJoin(ShapedQueryExpression
outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector,
LambdaExpression innerKeySelector, LambdaExpression resultSelector)
at
Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression
methodCallExpression) at
Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression
methodCallExpression) at
System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor
visitor) at
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at
Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression
methodCallExpression) at
Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression
methodCallExpression) at
System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor
visitor) at
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at
Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression
query) at
Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression
query, Boolean async) at
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase
database, Expression query, IModel model, Boolean async) at
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_01.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func
1 compiler) at
Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object
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.EntityQueryable
1.GetAsyncEnumerator(CancellationToken
cancellationToken) at
System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable1.GetAsyncEnumerator() at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable
1
source, CancellationToken cancellationToken) at
MoneyAppBackend.Controllers.ContestsController._GetLas10PastEvents(EventType
type, String language) in
/Users/juanjoseduran/Documents/Development/Projects/dotnet/MoneyAppBackend/MoneyAppBackend/Controllers/ContestsController.cs:line
106 at
MoneyAppBackend.Controllers.ContestsController.GetAll(EventType type,
String lang, String uuid) in
/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()
at
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper
mapper, ObjectMethodExecutor executor, Object controller, Object[]
arguments) at
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker
invoker, ValueTask`1 actionResultValueTask) at
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker
invoker, Task lastTask, State next, Scope scope, Object state, Boolean
isCompleted) at
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed
context) at
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State&
next, Scope& scope, Object& state, Boolean& isCompleted) at
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown --- at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker
invoker, Task lastTask, State next, Scope scope, Object state, Boolean
isCompleted) at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker
invoker, Task task, IDisposable scope) at
Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint
endpoint, Task requestTask, ILogger logger) at
Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext
context) at
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext
context)
如果我删除 Take 调用,它会正常工作。
就像@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();
这是我尝试执行的查询:
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; }
}
执行时出现如下异常:
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. System.InvalidOperationException: EF.Property called with wrong property name. at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitBinary(BinaryExpression binaryExpression) at Pomelo.EntityFrameworkCore.MySql.Query.ExpressionVisitors.Internal.MySqlSqlTranslatingExpressionVisitor.VisitBinary(BinaryExpression binaryExpression) at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.Translate(Expression expression) at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateExpression(Expression expression) at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.CreateJoinPredicate(Expression outerKey, Expression innerKey) at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.CreateJoinPredicate(ShapedQueryExpression outer, LambdaExpression outerKeySelector, ShapedQueryExpression inner, LambdaExpression innerKeySelector) at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateLeftJoin(ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, LambdaExpression resultSelector)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query) at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_01.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func
1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object 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.EntityQueryable
1.GetAsyncEnumerator(CancellationToken cancellationToken) at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable1.GetAsyncEnumerator() at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable
1 source, CancellationToken cancellationToken) at MoneyAppBackend.Controllers.ContestsController._GetLas10PastEvents(EventType type, String language) in /Users/juanjoseduran/Documents/Development/Projects/dotnet/MoneyAppBackend/MoneyAppBackend/Controllers/ContestsController.cs:line 106 at MoneyAppBackend.Controllers.ContestsController.GetAll(EventType type, String lang, String uuid) in /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() at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
如果我删除 Take 调用,它会正常工作。
就像@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();