【问题标题】:Use of Take() LINQ Method in Entity Framework Core v3.1.4在 Entity Framework Core v3.1.4 中使用 Take() LINQ 方法
【发布时间】:2020-09-16 17:46:56
【问题描述】:

我正在尝试在我的 API 请求中添加一个限制 GET 查询参数(即 ?limit=10),然后Take() LINQ 方法将使用此限制的值来仅获取我的结果数想。我想要做的是将 LINQ Take() 方法作为 LINQ-TO-T-SQL 查询的一部分包含在内,并将限制作为 SQL 查询的一部分执行。我尝试了以下代码。我还捕获了错误堆栈跟踪。

代码 1:对于此代码,我尝试在查询中的顶级资源上使用 Take()。然后之后(在q 的声明中),我正在执行与顶级资源相关的子查询。

baseQuery = baseQuery.Take(2);

var q = from doctor in baseQuery

        let sp = (from ds in db.DoctorSpecialty
                  join s in db.Specialty on ds.SpecialtyID equals s.SpecialtyID
                  where ds.DoctorID == doctor.DoctorID
                  select new
                  {
                      s.SpecialtyID,
                      s.Specialty1
                  }).ToList()

        let clinics = (from c in db.Clinic
                  where c.DoctorID == doctor.DoctorID && c.Active == true

                  let schedule = (from sc in db.Schedule
                                  where sc.ClinicID == c.ClinicID
                                    && sc.DoctorID == doctor.DoctorID
                                    && DoctorDirectoryConstants.ValidScheduleNotes.Contains(sc.Notes)
                                  select sc).ToList()

                  select new
                  {
                      c.ClinicID,
                      c.Street,
                      c.ClinicName,
                      c.ContactNumber,
                      c.City,
                      c.Province,
                      c.HomeNumber,
                      c.MobileNumber,
                      c.WorkNumber,
                      c.Email,
                      Schedules = schedule,
                  }).ToList() 
        select new
        {
            Doctor = doctor,
            Specialties = sp,
            Clinics = clinics

        };

var rs = q.ToList();

代码 1 的错误堆栈跟踪:

fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (5ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
      SELECT [t].[DoctorID], [t].[Address], [t].[AvailableInvites], [t].[Birthdate], [t].[City], [t].[CityID], [t].[ContactNumber], [t].[Country], [t].[DateRegistered], [t].[Description], [t].[DoctorUrl], [t].[Email], [t].[EmailActivated], [t].[EmailUID], [t].[EmailVerifiedFirstTime], [t].[Facebook], [t].[FirstName], [t].[Gender], [t].[GooglePlus], [t].[HomeNumber], [t].[Image], [t].[LastName], [t].[LinkedIn], [t].[MainSpecialty], [t].[ManuallyVerified], [t].[MedicalSchool], [t].[MedicalSchoolYear], [t].[MiddleName], [t].[MobileNumber], [t].[Nationality], [t].[OriginalIssueDate], [t].[PRCNumber], [t].[PageOkay], [t].[PatientNumber], [t].[PhicNumber], [t].[PractisingSince], [t].[Province], [t].[PtrNumber], [t].[Residency], [t].[ResidencyYear], [t].[S2Number], [t].[ShowPublicProfile], [t].[Status], [t].[Street], [t].[Suffix], [t].[Title], [t].[Twitter], [t].[UserID], [t].[Website], [t].[WorkNumber], [t].[Zipcode], [t0].[SpecialtyID], [t0].[Specialty], [t0].[Id], [t2].[ClinicID], [t2].[Street], [t2].[ClinicName], [t2].[ContactNumber], [t2].[City], [t2].[Province], [t2].[HomeNumber], [t2].[MobileNumber], [t2].[WorkNumber], [t2].[Email], [t2].[ScheduleID], [t2].[Active], [t2].[ClinicID0], [t2].[DateModified], [t2].[DayOfWeek], [t2].[DoctorID], [t2].[Notes], [t2].[StartFrom], [t2].[TimeEnd], [t2].[TimeStart], [t2].[Until]
      FROM (
          SELECT TOP(@__p_0) [d].[DoctorID], [d].[Address], [d].[AvailableInvites], [d].[Birthdate], [d].[City], [d].[CityID], [d].[ContactNumber], [d].[Country], [d].[DateRegistered], [d].[Description], [d].[DoctorUrl], [d].[Email], [d].[EmailActivated], [d].[EmailUID], [d].[EmailVerifiedFirstTime], [d].[Facebook], [d].[FirstName], [d].[Gender], [d].[GooglePlus], [d].[HomeNumber], [d].[Image], [d].[LastName], [d].[LinkedIn], [d].[MainSpecialty], [d].[ManuallyVerified], [d].[MedicalSchool], [d].[MedicalSchoolYear], [d].[MiddleName], [d].[MobileNumber], [d].[Nationality], [d].[OriginalIssueDate], [d].[PRCNumber], [d].[PageOkay], [d].[PatientNumber], [d].[PhicNumber], [d].[PractisingSince], [d].[Province], [d].[PtrNumber], [d].[Residency], [d].[ResidencyYear], [d].[S2Number], [d].[ShowPublicProfile], [d].[Status], [d].[Street], [d].[Suffix], [d].[Title], [d].[Twitter], [d].[UserID], [d].[Website], [d].[WorkNumber], [d].[Zipcode]
          FROM [Doctor] AS [d]
          WHERE [d].[Status] = 'good'
      ) AS [t]
      LEFT JOIN (
          SELECT [s].[SpecialtyID], [s].[Specialty], [d0].[Id], [d0].[DoctorID]
          FROM [DoctorSpecialty] AS [d0]
          INNER JOIN [Specialty] AS [s] ON [d0].[SpecialtyID] = [s].[SpecialtyID]
      ) AS [t0] ON [t].[DoctorID] = [t0].[DoctorID]
      LEFT JOIN (
          SELECT [c].[ClinicID], [c].[Street], [c].[ClinicName], [c].[ContactNumber], [c].[City], [c].[Province], [c].[HomeNumber], [c].[MobileNumber], [c].[WorkNumber], [c].[Email], [t1].[ScheduleID], [t1].[Active], [t1].[ClinicID] AS [ClinicID0], [t1].[DateModified], [t1].[DayOfWeek], [t1].[DoctorID], [t1].[Notes], [t1].[StartFrom], [t1].[TimeEnd], [t1].[TimeStart], [t1].[Until], [c].[DoctorID] AS [DoctorID0]
          FROM [Clinic] AS [c]
          LEFT JOIN (
              SELECT [s0].[ScheduleID], [s0].[Active], [s0].[ClinicID], [s0].[DateModified], [s0].[DayOfWeek], [s0].[DoctorID], [s0].[Notes], [s0].[StartFrom], [s0].[TimeEnd], [s0].[TimeStart], [s0].[Until]
              FROM [Schedule] AS [s0]
              WHERE ([s0].[DoctorID] = [d].[DoctorID]) AND [s0].[Notes] IN (N'Walk-In', N'By Appointment')
          ) AS [t1] ON [c].[ClinicID] = [t1].[ClinicID]
          WHERE [c].[Active] = CAST(1 AS bit)
      ) AS [t2] ON [t].[DoctorID] = [t2].[DoctorID0]
      ORDER BY [t].[DoctorID], [t0].[Id], [t0].[SpecialtyID], [t2].[ClinicID], [t2].[ScheduleID]
fail: Microsoft.EntityFrameworkCore.Query[10100]
      An exception occurred while iterating over the results of a query for context type 'SeriousMDCommonsCore.Models.Database.SeriousmdEntitiesContext'.
      Microsoft.Data.SqlClient.SqlException (0x80131904): The multi-part identifier "d.DoctorID" could not be bound.
         at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
         at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
         at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
         at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
         at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
         at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData()
         at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
         at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
         at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method)
         at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
         at Microsoft.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
         at Microsoft.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
         at System.Data.Common.DbCommand.ExecuteReader()
         at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
         at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
         at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
         at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
      ClientConnectionId:0b10b611-bd0f-4fcb-a543-fdbe530fc029
      Error Number:4104,State:1,Class:16
Microsoft.Data.SqlClient.SqlException (0x80131904): The multi-part identifier "d.DoctorID" could not be bound.
   at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData()
   at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method)
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at Microsoft.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
   at Microsoft.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader()
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
ClientConnectionId:0b10b611-bd0f-4fcb-a543-fdbe530fc029
Error Number:4104,State:1,Class:16
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HM03JVLBFS8O", Request id "0HM03JVLBFS8O:00000001": An unhandled exception was thrown by the application.
Microsoft.Data.SqlClient.SqlException (0x80131904): The multi-part identifier "d.DoctorID" could not be bound.
   at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData()
   at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method)
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at Microsoft.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
   at Microsoft.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader()
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   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.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
ClientConnectionId:0b10b611-bd0f-4fcb-a543-fdbe530fc029
Error Number:4104,State:1,Class:16

代码 2:在这里,我不是在 baseQuery 中执行 Take(),而是在最终查询表达式 q 中执行 Take()。我还添加了doctor.DoctorID 作为某种id,我认为需要将其提供给Take() LINQ 方法

var q = from doctor in baseQuery

        let sp = (from ds in db.DoctorSpecialty
                  join s in db.Specialty on ds.SpecialtyID equals s.SpecialtyID
                  where ds.DoctorID == doctor.DoctorID
                  select new
                  {
                      s.SpecialtyID,
                      s.Specialty1
                  }).ToList()

        let clinics = (from c in db.Clinic
                  where c.DoctorID == doctor.DoctorID && c.Active == true

                  let schedule = (from sc in db.Schedule
                                  where sc.ClinicID == c.ClinicID
                                    && sc.DoctorID == doctor.DoctorID
                                    && DoctorDirectoryConstants.ValidScheduleNotes.Contains(sc.Notes)
                                  select sc).ToList()

                  select new
                  {
                      c.ClinicID,
                      c.Street,
                      c.ClinicName,
                      c.ContactNumber,
                      c.City,
                      c.Province,
                      c.HomeNumber,
                      c.MobileNumber,
                      c.WorkNumber,
                      c.Email,
                      Schedules = schedule,
                  }).ToList() 
        select new
        {
            doctor.DoctorID,
            Doctor = doctor,
            Specialties = sp,
            Clinics = clinics

        };

q = q.Take(2);

var rs = q.ToList();

代码 2 的错误堆栈跟踪:这里的错误与代码 2 的错误有所不同,似乎Take() LINQ 方法正在使用添加的索引,但仍然抛出错误。

fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HM03K296O68T", Request id "0HM03K296O68T:00000001": An unhandled exception was thrown by the application.
System.InvalidOperationException: Processing of the LINQ expression '(ProjectionBindingExpression: 0)' by 'RelationalProjectionBindingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information.
   at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitNew(NewExpression newExpression)
   at System.Linq.Expressions.NewExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
   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__DisplayClass9_0`1.<Execute>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, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   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.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

回到我的问题,如何将Take() LINQ 方法集成为我的 LINQ-TO-T-SQL 查询的一部分,以便我的所有查询都将通过 EF Core,并且所有查询操作都将在数据库中执行?

【问题讨论】:

  • 您使用的是哪个版本的 EF 内核?
  • @GuruStron 我正在使用 EF Core v3.1.4
  • 通常当你有 let 时,ToList() 这些就像 sql 中的 cte's/temp 表,所以把它分开以便更容易理解,也就是我要做的就是写我的 sql希望它生成然后将其转换为linq。当您想要做的事情不是直截了当时,它会更容易,因为您更好地了解工具的局限性。你可以在 sql 中做的任何事情都可以在 linq 中做。所以在sql中进行查询,然后它将帮助如何在linq中进行查询。
  • 我的意思是只要你ToList() 在你执行它的任何部分。但有时必须这样做……比如 CTE/Temp 表。

标签: c# asp.net-mvc linq asp.net-core entity-framework-core


【解决方案1】:

在第一个查询中尝试更改doctor.DoctorID in:

let schedule = (from sc in db.Schedule
                where sc.ClinicID == c.ClinicID
                && sc.DoctorID == doctor.DoctorID
                && DoctorDirectoryConstants.ValidScheduleNotes.Contains(sc.Notes)
                select sc)

c.DoctorID:

let schedule = (from sc in db.Schedule
                where sc.ClinicID == c.ClinicID
                && sc.DoctorID == c.DoctorID
                && DoctorDirectoryConstants.ValidScheduleNotes.Contains(sc.Notes)
                select sc)

UPD

如果您浏览 SQL,您将看到为时间表生成的代码:

LEFT JOIN (
              SELECT [s0].[ScheduleID], [s0].[Active], [s0].[ClinicID], [s0].[DateModified], [s0].[DayOfWeek], [s0].[DoctorID], [s0].[Notes], [s0].[StartFrom], [s0].[TimeEnd], [s0].[TimeStart], [s0].[Until]
              FROM [Schedule] AS [s0]
              WHERE ([s0].[DoctorID] = [d].[DoctorID]) AND [s0].[Notes] IN (N'Walk-In', N'By Appointment')
          ) AS [t1] ON [c].[ClinicID] = [t1].[ClinicID]

查看它具有 WHERE ([s0].[DoctorID] = [d].[DoctorID]) 条件的 where 子句,该条件引用了无法访问的 [d].[DoctorID],因为它只能在执行 Take 的根子选择中访问。似乎 EF Core 中存在一个令人费解的错误。

【讨论】:

  • 嗨@GuruStron,它现在适用于代码 1。非常感谢!你能解释一下它工作的原因吗?
【解决方案2】:

代码 3:此版本的代码通过Take() LINQ 方法成功返回了我想要的结果数。但是,Take() 正在对已加载到客户端或内存中的数据/集合执行。所以这个 Take() 执行 LINQ-TO-Collections 查询而不是 LINQ-TO-T-SQL 并且不通过 EF Core。

var q = from doctor in baseQuery

        let sp = (from ds in db.DoctorSpecialty
                  join s in db.Specialty on ds.SpecialtyID equals s.SpecialtyID
                  where ds.DoctorID == doctor.DoctorID
                  select new
                  {
                      s.SpecialtyID,
                      s.Specialty1
                  }).ToList()

        let clinics = (from c in db.Clinic
                  where c.DoctorID == doctor.DoctorID && c.Active == true

                  let schedule = (from sc in db.Schedule
                                  where sc.ClinicID == c.ClinicID
                                    && sc.DoctorID == doctor.DoctorID
                                    && DoctorDirectoryConstants.ValidScheduleNotes.Contains(sc.Notes)
                                  select sc).ToList()

                  select new
                  {
                      c.ClinicID,
                      c.Street,
                      c.ClinicName,
                      c.ContactNumber,
                      c.City,
                      c.Province,
                      c.HomeNumber,
                      c.MobileNumber,
                      c.WorkNumber,
                      c.Email,
                      Schedules = schedule,
                  }).ToList() 
        select new
        {
            Doctor = doctor,
            Specialties = sp,
            Clinics = clinics

        };

var rs = q.ToList();

rs = rs.AsEnumerable().Take(2).ToList();

【讨论】:

  • 仅供参考,您不需要 AsEnumerable() in rs = rs.AsEnumerable().Take(2).ToList()
  • 您好@GuruStron 指出。谢谢!我试过了,它可以工作rs = rs.Take(2).ToList();
猜你喜欢
  • 2021-02-27
  • 1970-01-01
  • 2019-06-27
  • 2021-07-20
  • 2022-08-20
  • 2017-04-25
  • 2020-05-17
  • 2020-08-27
  • 1970-01-01
相关资源
最近更新 更多