0
votes

I need to create two odata controllers that return the same result set.

Specifically, the result sets is returned from two stored procedures, which receive a lot of parameters, and do some heavy processing on server.

Both SPs receive exact the same params and return the same data, but they accomplish the search in different ways, and I need to do this for some performance tests and comparisons.

The SPs are mapped to functions in EF.

So I need to have two odata controllers that, each of them, call a different SP, but return the same data type.

My code is as follows:

Controller 1

<Authorize>
Public Class SearchController
    Inherits ODataController

    Private _dc As New ModelDC

    ' GET odata/Search
    <Queryable>
    Function GetSearch(<FromURI> search As SearchParam) As IQueryable(Of SearchResult)
        dim result =  _dc.Search(search.Parm1, search.Param2, ...).ToList
        Return result.AsQueryable
    end function

Controller 2

<Authorize>
Public Class SearchV2Controller
    Inherits ODataController

    Private _dc As New ModelDC

    ' GET odata/Search
    <Queryable>
    Function GetSearch(<FromURI> p1 as string, <FromURI> p2 as string, ...) As IQueryable(Of SearchResult)
        dim result =  _dc.SearchV2(p1, p2, ...).ToList
        Return result.AsQueryable
    end function

And the odata route registration in WebApiConfig.Register

Dim builder As New ODataConventionModelBuilder
builder.EntitySet(Of SearchResult)("Search")
config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel())

builder = New ODataConventionModelBuilder
builder.EntitySet(Of SearchResult)("SearchV2")
config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel())

However, when I start the app, I get the following error:

Server Error in '/' Application. Exception of type 'System.OutOfMemoryException' was thrown. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.] System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +0
System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +34
System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +152
System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection) +77
System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +16 System.Reflection.Assembly.Load(String assemblyString) +28
System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +38

[ConfigurationErrorsException: Exception of type 'System.OutOfMemoryException' was thrown.]
System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +736
System.Web.Configuration.CompilationSection.LoadAllAssembliesFromAppDomainBinDirectory() +217 System.Web.Configuration.CompilationSection.LoadAssembly(AssemblyInfo ai) +130
System.Web.Compilation.BuildManager.GetReferencedAssemblies(CompilationSection compConfig) +170
System.Web.Compilation.BuildManager.GetPreStartInitMethodsFromReferencedAssemblies() +91 System.Web.Compilation.BuildManager.CallPreStartInitMethods(String preStartInitListPath, Boolean& isRefAssemblyLoaded) +284
System.Web.Compilation.BuildManager.ExecutePreAppStart() +153
System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +521

[HttpException (0x80004005): Exception of type 'System.OutOfMemoryException' was thrown.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +9930508 System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +101 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +254

What is the problem? Is it the fact that both controllers are defined with the same return type? I can, of course, create a different entity for the second SP (with exact the same structure), and map the result of each SP to different result class, and I assume that will work, but I prefer to have them both returning the same type of result.

What am I doing wrong?

Thanks

PS. I have the result converted first ToList and then returned AsQueryable because I need to support $inlinecount odata param, and EF-mapped SPs uses DataReader inside, which doesn't allow to re-enumerate the set to get the count first and then return the actual data. If anyone has a better idea to handle this, please let me know also.

1
The "OutOfMemoryException" is a red herring here, the question is very valid however. - Chris Schaller

1 Answers

0
votes

why do you map the same route with different Edm Model? Can you merge them together as?

Dim builder As New ODataConventionModelBuilder
builder.EntitySet(Of SearchResult)("Search")
builder.EntitySet(Of SearchResult)("SearchV2")
config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel())