如何在ODataQueryOptions上启用$ expand和$ select?

时间:2014-02-10 22:03:30

标签: c# linq odata

问题已于here开始,我无法在$select上致电$expandresults

鉴于:

            var results = options.ApplyTo(_uow.Repository<ContentType>()
                .Query()
                .Get()
                .Include(u => u.User)
                .Where(u => u.UserId == userId)
                .OrderBy(o => o.Description)).Cast<ContentType>()
                .Select(x => new ContentTypeDTO()
                {
                    //projection goes here
                    ContentTypeId = x.ContentTypeId,
                    Description = x.Description,
                    UserDTO = new UserDTO 
                    { 
                        UserId = x.UserId,
                        UserName = x.User.UserName
                    }
                });

例外:

  

无法转换类型   “System.Web.Http.OData.Query.Expressions.SelectExpandBinder + SelectSome`1 [[Project.DAL.Data.Models.ContentType,   Project.DAL.Data,Version = 1.0.0.0,Culture = neutral,   PublicKeyToken = null]]'键入'Project.DAL.Data.Models.ContentType'。   LINQ to Entities仅支持转换EDM原语或枚举   类型“。

根据this solution,我了解当$select$expand应用于结果时,它不再是ContentType,正如{Cast<ContentType>()所期望的那样1}}。该解决方案使用HierarchyNodeExpressionVisitor,我无法找到它。

我想使用'options.ApplyTo()',因为我希望在数据库服务器上完成过滤,以确保我不会收回数十万行的虚增数据集。

是否有建议的解决方法?

- 更新 -

在下面使用@Schandlich建议的解决方案时,操作仍然失败,并使用Ok覆盖:

当地人:

+       this    {Project.AdminWebsite.Api.Controllers.ContentTypeController}    Project.AdminWebsite.Api.Controllers.ODataBaseController {Project.AdminWebsite.Api.Controllers.ContentTypeController}
+       content {System.Data.Entity.Infrastructure.DbQuery<Project.Core.UI.Models.ContentTypeDTO>}  object {System.Data.Entity.Infrastructure.DbQuery<Project.Core.UI.Models.ContentTypeDTO>}
+       type    {Name = "DbQuery`1" FullName = "System.Data.Entity.Infrastructure.DbQuery`1[[Project.Core.UI.Models.ContentTypeDTO, Project.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"} System.Type {System.RuntimeType}
+       resultType  {Name = "OkNegotiatedContentResult`1" FullName = "System.Web.Http.Results.OkNegotiatedContentResult`1[[System.Data.Entity.Infrastructure.DbQuery`1[[Project.Core.UI.Models.ContentTypeDTO, Project.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}    System.Type {System.RuntimeType}
+       result  {System.Web.Http.Results.OkNegotiatedContentResult<System.Data.Entity.Infrastructure.DbQuery<Project.Core.UI.Models.ContentTypeDTO>>}   System.Web.Http.IHttpActionResult {System.Web.Http.Results.OkNegotiatedContentResult<System.Data.Entity.Infrastructure.DbQuery<Project.Core.UI.Models.ContentTypeDTO>>}

调用堆栈:

>   Project.AdminWebsite.dll!Project.AdminWebsite.Api.Controllers.ODataBaseController.Ok(object content, System.Type type) Line 27  C#
    Project.AdminWebsite.dll!Project.AdminWebsite.Api.Controllers.ContentTypeController.Get(System.Web.Http.OData.Query.ODataQueryOptions<Project.DAL.Data.Models.ContentType> odataQueryOptions) Line 132  C#
    [Lightweight Function]  
    System.Web.Http.dll!System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.GetExecutor.AnonymousMethod__9(object instance, object[] methodParameters) Unknown
    System.Web.Http.dll!System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(object instance, object[] arguments)   Unknown
    System.Web.Http.dll!System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(System.Web.Http.Controllers.HttpControllerContext controllerContext, System.Collections.Generic.IDictionary<string,object> arguments, System.Threading.CancellationToken cancellationToken)  Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.HttpActionDescriptorTracer.ExecuteAsync.AnonymousMethod__1()    Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEndAsync<object>(System.Web.Http.Tracing.ITraceWriter traceWriter, System.Net.Http.HttpRequestMessage request, string category, System.Web.Http.Tracing.TraceLevel level, string operatorName, string operationName, System.Action<System.Web.Http.Tracing.TraceRecord> beginTrace, System.Func<System.Threading.Tasks.Task<object>> execute, System.Action<System.Web.Http.Tracing.TraceRecord,object> endTrace, System.Action<System.Web.Http.Tracing.TraceRecord> errorTrace)   Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.HttpActionDescriptorTracer.ExecuteAsync(System.Web.Http.Controllers.HttpControllerContext controllerContext, System.Collections.Generic.IDictionary<string,object> arguments, System.Threading.CancellationToken cancellationToken) Unknown
    System.Web.Http.dll!System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsyncCore()  Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsyncCore>(ref System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsyncCore stateMachine)  Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsyncCore>(ref System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsyncCore stateMachine)  Unknown
    System.Web.Http.dll!System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsyncCore(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) Unknown
    System.Web.Http.dll!System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.HttpActionInvokerTracer.System.Web.Http.Controllers.IHttpActionInvoker.InvokeActionAsync.AnonymousMethod__1()   Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEndAsync<System.Net.Http.HttpResponseMessage>(System.Web.Http.Tracing.ITraceWriter traceWriter, System.Net.Http.HttpRequestMessage request, string category, System.Web.Http.Tracing.TraceLevel level, string operatorName, string operationName, System.Action<System.Web.Http.Tracing.TraceRecord> beginTrace, System.Func<System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage>> execute, System.Action<System.Web.Http.Tracing.TraceRecord,System.Net.Http.HttpResponseMessage> endTrace, System.Action<System.Web.Http.Tracing.TraceRecord> errorTrace)    Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.HttpActionInvokerTracer.System.Web.Http.Controllers.IHttpActionInvoker.InvokeActionAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) Unknown
    System.Web.Http.dll!System.Web.Http.Controllers.ActionFilterResult.ActionInvoker.InvokeActionAsync()    Unknown
    System.Web.Http.dll!System.Web.Http.Controllers.ActionFilterResult.ExecuteAsync()   Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<System.Web.Http.Controllers.ActionFilterResult.ExecuteAsync>(ref System.Web.Http.Controllers.ActionFilterResult.ExecuteAsync stateMachine)    Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.Controllers.ActionFilterResult.ExecuteAsync>(ref System.Web.Http.Controllers.ActionFilterResult.ExecuteAsync stateMachine)    Unknown
    System.Web.Http.dll!System.Web.Http.Controllers.ActionFilterResult.ExecuteAsync(System.Threading.CancellationToken cancellationToken)   Unknown
    System.Web.Http.dll!System.Web.Http.ApiController.ExecuteAsync(System.Web.Http.Controllers.HttpControllerContext controllerContext, System.Threading.CancellationToken cancellationToken)   Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.HttpControllerTracer.ExecuteAsyncCore() Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<System.Web.Http.Tracing.Tracers.HttpControllerTracer.ExecuteAsyncCore>(ref System.Web.Http.Tracing.Tracers.HttpControllerTracer.ExecuteAsyncCore stateMachine)    Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.Tracing.Tracers.HttpControllerTracer.ExecuteAsyncCore>(ref System.Web.Http.Tracing.Tracers.HttpControllerTracer.ExecuteAsyncCore stateMachine)    Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.HttpControllerTracer.ExecuteAsyncCore(System.Web.Http.Controllers.HttpControllerContext controllerContext, System.Threading.CancellationToken cancellationToken)    Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.HttpControllerTracer.System.Web.Http.Controllers.IHttpController.ExecuteAsync.AnonymousMethod__0()  Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEndAsync<System.Net.Http.HttpResponseMessage>(System.Web.Http.Tracing.ITraceWriter traceWriter, System.Net.Http.HttpRequestMessage request, string category, System.Web.Http.Tracing.TraceLevel level, string operatorName, string operationName, System.Action<System.Web.Http.Tracing.TraceRecord> beginTrace, System.Func<System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage>> execute, System.Action<System.Web.Http.Tracing.TraceRecord,System.Net.Http.HttpResponseMessage> endTrace, System.Action<System.Web.Http.Tracing.TraceRecord> errorTrace)    Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.HttpControllerTracer.System.Web.Http.Controllers.IHttpController.ExecuteAsync(System.Web.Http.Controllers.HttpControllerContext controllerContext, System.Threading.CancellationToken cancellationToken)    Unknown
    System.Web.Http.dll!System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) Unknown
    System.Web.Http.dll!System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync() Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync>(ref System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync stateMachine)    Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync>(ref System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync stateMachine)    Unknown
    System.Web.Http.dll!System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) Unknown
    System.Net.Http.dll!System.Net.Http.HttpMessageInvoker.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)  Unknown
    System.Web.Http.dll!System.Web.Http.Dispatcher.HttpRoutingDispatcher.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)    Unknown
    System.Net.Http.dll!System.Net.Http.DelegatingHandler.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)   Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.RequestMessageHandlerTracer.AnonymousMethod__FabricatedMethod6()    Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.RequestMessageHandlerTracer.SendAsync.AnonymousMethod__1()  Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEndAsync<System.Net.Http.HttpResponseMessage>(System.Web.Http.Tracing.ITraceWriter traceWriter, System.Net.Http.HttpRequestMessage request, string category, System.Web.Http.Tracing.TraceLevel level, string operatorName, string operationName, System.Action<System.Web.Http.Tracing.TraceRecord> beginTrace, System.Func<System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage>> execute, System.Action<System.Web.Http.Tracing.TraceRecord,System.Net.Http.HttpResponseMessage> endTrace, System.Action<System.Web.Http.Tracing.TraceRecord> errorTrace)    Unknown
    System.Web.Http.dll!System.Web.Http.Tracing.Tracers.RequestMessageHandlerTracer.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) Unknown
    System.Net.Http.dll!System.Net.Http.DelegatingHandler.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)   Unknown
    System.Web.Http.dll!System.Web.Http.HttpServer.AnonymousMethod__FabricatedMethod9() Unknown
    System.Web.Http.dll!System.Web.Http.HttpServer.SendAsync()  Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<System.Web.Http.HttpServer.SendAsync>(ref System.Web.Http.HttpServer.SendAsync stateMachine)  Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.__Canon>.Start<System.Web.Http.HttpServer.SendAsync>(ref System.Web.Http.HttpServer.SendAsync stateMachine)  Unknown
    System.Web.Http.dll!System.Web.Http.HttpServer.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)  Unknown
    System.Net.Http.dll!System.Net.Http.HttpMessageInvoker.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)  Unknown
    System.Web.Http.WebHost.dll!System.Web.Http.WebHost.HttpControllerHandler.ProcessRequestAsyncCore() Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<System.Web.Http.WebHost.HttpControllerHandler.ProcessRequestAsyncCore>(ref System.Web.Http.WebHost.HttpControllerHandler.ProcessRequestAsyncCore stateMachine)    Unknown
    mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<System.Web.Http.WebHost.HttpControllerHandler.ProcessRequestAsyncCore>(ref System.Web.Http.WebHost.HttpControllerHandler.ProcessRequestAsyncCore stateMachine)    Unknown
    System.Web.Http.WebHost.dll!System.Web.Http.WebHost.HttpControllerHandler.ProcessRequestAsyncCore(System.Web.HttpContextBase contextBase)   Unknown
    System.Web.Http.WebHost.dll!System.Web.Http.WebHost.HttpControllerHandler.ProcessRequestAsync(System.Web.HttpContext context)   Unknown
    System.Web.dll!System.Web.HttpTaskAsyncHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest.AnonymousMethod__0()    Unknown
    System.Web.dll!System.Web.TaskAsyncHelper.BeginTask(System.Func<System.Threading.Tasks.Task> taskFunc, System.AsyncCallback callback, object state) Unknown
    System.Web.dll!System.Web.HttpTaskAsyncHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext context, System.AsyncCallback cb, object extraData)  Unknown
    System.Web.dll!System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()  Unknown
    System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step, ref bool completedSynchronously)  Unknown
    System.Web.dll!System.Web.HttpApplication.PipelineStepManager.ResumeSteps(System.Exception error)   Unknown
    System.Web.dll!System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext context, System.AsyncCallback cb)  Unknown
    System.Web.dll!System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest wr, System.Web.HttpContext context)    Unknown
    System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
    System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags)   Unknown
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
    System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags)   Unknown
    [AppDomain Transition]  

错误讯息:

Unable to cast the type 'System.Web.Http.OData.Query.Expressions.SelectExpandBinder+SelectAll`1[[Project.DAL.Data.Models.ContentType, Project.DAL.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' to type 'Project.DAL.Data.Models.ContentType'. LINQ to Entities only supports casting EDM primitive or enumeration types.

1 个答案:

答案 0 :(得分:4)

来自$select and $expand break ODataQueryOptions -- how to fix?

public IHttpActionResult Get(ODataQueryOptions<YourEntity> odataQueryOptions)
{
    //Your applyTo logic and results.

    if (odataQueryOptions.SelectExpand != null)
    {
        Request.SetSelectExpandClause(odataQueryOptions.SelectExpand.SelectExpandClause);
    }

    return Ok(results, results.GetType());
}

private IHttpActionResult Ok(object content, Type type)
{
    Type resultType = typeof(OkNegotiatedContentResult<>).MakeGenericType(type);
    return Activator.CreateInstance(resultType, content, this) as IHttpActionResult;
}

但正如我在您提出的其他问题中所述,如果可以,请继续寻找避免手动应用结果的方法。