GithubHelp home page GithubHelp logo

Comments (30)

voronov-maxim avatar voronov-maxim commented on June 8, 2024 1

For example, in OData/WebApi I can take in the queryOptions and applying them manually in the controller, instead of just applying a [Queryable] attribute. This returns a IQueryable instance which I can continue to add .Where(), .Select(), joins, etc. I use this pattern for 2 cases currently.
1.) Add additional filters to the query based on the user (HttpContext.User.Identity) to restrict the type of results they can return (without using say row level filtering at the database level)
2.) Use the query to produce a different result, such as a data export (build an excel file, csv, etc).

Add support filter and select result

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

@voronov-maxim I figured out if I disable the queryCount cache assertion in DbFixureInitDb...

image

I was able to get a better error as to why the test wasn't working (I had accidentally put $expand=AltCustomers instead of $expand=AltCustomer`). This test now shows the issue properly:

[Theory]
[InlineData(0, false)]
[InlineData(1, false)]
[InlineData(0, true)]
[InlineData(1, true)]
public async Task ExpandNullableNestedSelect(int pageSize, bool navigationNextLink)
{
    var parameters = new QueryParameters<Order>()
    {
        RequestUri = "Orders?$expand=AltCustomer($select=Name)&$orderby=Id",
        Expression = t => t.Include(o => o.AltCustomer).OrderBy(o => o.Id),
        NavigationNextLink = navigationNextLink,
        PageSize = pageSize
    };
    await Fixture.Execute(parameters).ConfigureAwait(false);
}

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

As always, thanks @voronov-maxim. Could you cut another NuGet release when you get a chance?

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

Hi @techniq , thanks for the test reproducing error.
If you use controllers, then get the performance penalty due to additional type transformation
Without controllers: EF(Tuple)->Json
With controller: EF(Tuple)->DTO->Json

Nuget with fix

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

@voronov-maxim when you refer to controllers, do you mean ASP.NET Controllers, or some other type of controller?

Also, I noticed the updated ODataToEntity package to 1.6.1, but ODataToEntity.EfCore and ODataToEntity.AspNet are still 1.6.0. Should I be explicitly reference the ODataToEntity package when I use these, or should those be updated to 1.6.1 as well?

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

when you refer to controllers, do you mean ASP.NET Controllers, or some other type of controller?

OdataToEntity.AspNetCore.OeControllerBase

Should I be explicitly reference the ODataToEntity package when I use these, or should those be updated to 1.6.1 as well?

Assembly version no changed

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

where OdataToEntity.AspNetCore reference ODataToEntity, I didn't know if it needed to be updated/republished as well.

image

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

Hmm, I'm still getting the same exception as the original report (including when I pulled down the latest sources and uses project references instead of NuGet packages).

Microsoft.OData.ODataException: The property 'Name[Nullable=False]' of type 'Edm.String' has a null value, which is not allowed.
   at Microsoft.OData.WriterValidationUtils.ValidateNullPropertyValue(IEdmTypeReference expectedPropertyTypeReference, String propertyName, IEdmModel model)
   at Microsoft.OData.WriterValidator.ValidateNullPropertyValue(IEdmTypeReference expectedPropertyTypeReference, String propertyName, Boolean isTopLevel, IEdmModel model)
   at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteNullProperty(ODataProperty property)
   at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperties(IEdmStructuredType owningType, IEnumerable`1 properties, Boolean isComplexValue, IDuplicatePropertyNameChecker duplicatePropertyNameChecker)
   at Microsoft.OData.JsonLight.ODataJsonLightWriter.StartResource(ODataResource resource)
   at Microsoft.OData.ODataWriterCore.InterceptException(Action action)
   at OdataToEntity.AspNetCore.ODataResult`1.WriteEntry(ODataWriter writer, Object entity, EntityPropertiesInfo& entityPropertiesInfo) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 242
   at OdataToEntity.AspNetCore.ODataResult`1.WriteNavigationProperty(ODataWriter writer, Object value, PropertyInfo navigationProperty) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 282
   at OdataToEntity.AspNetCore.ODataResult`1.WriteEntry(ODataWriter writer, Object entity, EntityPropertiesInfo& entityPropertiesInfo) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 245
   at OdataToEntity.AspNetCore.ODataResult`1.SerializeAsync(ODataWriter writer) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 226
   at OdataToEntity.AspNetCore.ODataResult`1.ExecuteResultAsync(ActionContext context) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 144
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

This is when I hit http://localhost:5000/odata/Accounts?$top=50&$expand=Department($select=Name).

Controller

[Route("odata/[controller]")]
public class AccountsController : OeControllerBase
{
    public AccountsController(OeDataAdapter dataAdapter, IEdmModel edmModel)
            : base(dataAdapter, edmModel)
    {
    }

    [HttpGet]
    public ODataResult<Account> Get()
    {
        var asyncEnumerator = GetAsyncEnumerator(HttpContext, HttpContext.Response.Body);
        return OData<Account>(asyncEnumerator);
    }

    [HttpGet("$count")]
    public async Task<IActionResult> Count()
    {
        var asyncEnumerator = GetAsyncEnumerator(HttpContext, HttpContext.Response.Body);
        return await ODataScalar(asyncEnumerator);
    }
}

Relevant parts of Models

abstract public class AccountModel : EntityModelWithId<int>
{
    public virtual int? DepartmentId { get; set; }
    // other properties...
}

public class Account : AccountModel
{
    public virtual Department Department { get; set; }
    // other properties...
}

abstract public class DepartmentModel : EntityModelWithId<int>
{
    // other properties...
}

public class Department : DepartmentModel
{
    public virtual ICollection<Account> Accounts { get; set; }
    // other properties...
}

I don't know if the inheritance model is causing a problem, or if there is an issue with how the controller is setup vs. the test (I confirmed the new test is passing locally).

Any thoughts?

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

@voronov-maxim btw, I just ran this using OdataToEntity.Test.AspMvcServer accessing http://localhost:5000/api/Orders?$expand=AltCustomer($select=Name)&$orderby=Id (same as the ExpandNullableNestedSelect test) and it produced the same ODataException

Microsoft.OData.ODataException: The property 'Name[Nullable=False]' of type 'Edm.String' has a null value, which is not allowed.
   at Microsoft.OData.WriterValidationUtils.ValidateNullPropertyValue(IEdmTypeReference expectedPropertyTypeReference, String propertyName, IEdmModel model)
   at Microsoft.OData.WriterValidator.ValidateNullPropertyValue(IEdmTypeReference expectedPropertyTypeReference, String propertyName, Boolean isTopLevel, IEdmModel model)
   at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteNullProperty(ODataProperty property)
   at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperties(IEdmStructuredType owningType, IEnumerable`1 properties, Boolean isComplexValue, IDuplicatePropertyNameChecker duplicatePropertyNameChecker)
   at Microsoft.OData.JsonLight.ODataJsonLightWriter.StartResource(ODataResource resource)
   at Microsoft.OData.ODataWriterCore.InterceptException(Action action)
   at OdataToEntity.AspNetCore.ODataResult`1.WriteEntry(ODataWriter writer, Object entity, EntityPropertiesInfo& entityPropertiesInfo) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 242
   at OdataToEntity.AspNetCore.ODataResult`1.WriteNavigationProperty(ODataWriter writer, Object value, PropertyInfo navigationProperty) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 282
   at OdataToEntity.AspNetCore.ODataResult`1.WriteEntry(ODataWriter writer, Object entity, EntityPropertiesInfo& entityPropertiesInfo) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 245
   at OdataToEntity.AspNetCore.ODataResult`1.SerializeAsync(ODataWriter writer) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 226
   at OdataToEntity.AspNetCore.ODataResult`1.ExecuteResultAsync(ActionContext context) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 144
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

error due to additional transformation EF(Tuple)->DTO

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

Is that something I need to handle in my controller? If so, could you provide an example?

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

No, I'll fix it in an hour

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

@techniq
publish nuget 1.6.2

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

@voronov-maxim I tested the fix with the original issue and it's working now, thanks!

I did just run into a similar issue but with ICollection properties. For example, to reproduce using OdataToEntity.Test.AspMvcServer, the following:

  • http://localhost:5000/api/Orders?$expand=Items($expand=Order)

produces:

System.InvalidCastException: Unable to cast object of type 'System.Tuple`2[OdataToEntity.Test.Model.Order,System.Collections.Generic.IEnumerable`1[System.Tuple`2[OdataToEntity.Test.Model.OrderItem,OdataToEntity.Test.Model.Order]]]' to type 'System.Tuple`2[OdataToEntity.Test.Model.OrderItem,OdataToEntity.Test.Model.Order]'.
   at lambda_method(Closure , Object )
   at OdataToEntity.Parsers.OeEntryFactory.GetValue(Object value, Nullable`1& count) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity/Parsers/OeEntryFactory.cs:line 82
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.CreateNestedEntity(OeEntryFactory entryFactory, Object value, Type nestedEntityType) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 81
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.SetNavigationProperty(OeEntryFactory navigationLink, Object value, Object ownerEntry) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 147
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.<CreateNestedEntity>g__CreateEntity|9_0(Object entity, <>c__DisplayClass9_0& ) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 108
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.CreateNestedEntity(OeEntryFactory entryFactory, Object value, Type nestedEntityType) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 89
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.SetNavigationProperty(OeEntryFactory navigationLink, Object value, Object ownerEntry) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 147
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.MoveNext(CancellationToken cancellationToken) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 132
   at OdataToEntity.AspNetCore.ODataResult`1.SerializeAsync(ODataWriter writer) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 212
   at OdataToEntity.AspNetCore.ODataResult`1.ExecuteResultAsync(ActionContext context) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 134
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
�[40m�[32minfo�[39m�[22m�[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 1373.406ms 200 application/json;odata.metadata=minimal;odata.streaming=true;charset=utf-8
      Request finished in 1373.406ms 200 application/json;odata.metadata=minimal;odata.streaming=true;charset=utf-8
The thread 5070630 has exited with code 0 (0x0).

The same is true for http://localhost:5000/api/Customers?$expand=Orders($expand=Items) (another example that wasn't recursive => Orders->Items->Order

System.InvalidCastException: Unable to cast object of type 'System.Tuple`2[OdataToEntity.Test.Model.Customer,System.Collections.Generic.IEnumerable`1[System.Tuple`2[OdataToEntity.Test.Model.Order,System.Collections.Generic.ICollection`1[OdataToEntity.Test.Model.OrderItem]]]]' to type 'System.Tuple`2[OdataToEntity.Test.Model.Order,System.Collections.Generic.ICollection`1[OdataToEntity.Test.Model.OrderItem]]'.
   at lambda_method(Closure , Object )
   at OdataToEntity.Parsers.OeEntryFactory.GetValue(Object value, Nullable`1& count) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity/Parsers/OeEntryFactory.cs:line 82
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.CreateNestedEntity(OeEntryFactory entryFactory, Object value, Type nestedEntityType) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 81
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.SetNavigationProperty(OeEntryFactory navigationLink, Object value, Object ownerEntry) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 147
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.<CreateNestedEntity>g__CreateEntity|9_0(Object entity, <>c__DisplayClass9_0& ) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 108
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.CreateNestedEntity(OeEntryFactory entryFactory, Object value, Type nestedEntityType) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 89
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.SetNavigationProperty(OeEntryFactory navigationLink, Object value, Object ownerEntry) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 147
   at OdataToEntity.AspNetCore.OeEntityAsyncEnumerator`1.MoveNext(CancellationToken cancellationToken) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/OeEntityAsyncEnumerator.cs:line 132
   at OdataToEntity.AspNetCore.ODataResult`1.SerializeAsync(ODataWriter writer) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 212
   at OdataToEntity.AspNetCore.ODataResult`1.ExecuteResultAsync(ActionContext context) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.AspNetCore/ODataResult.cs:line 134
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 1131.421ms 200 application/json;odata.metadata=minimal;odata.streaming=true;charset=utf-8

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

Hi @techniq, fix $expand($expand) changed only package OdataToEntity.AspNetCore
Nuget

Why you use AspNetCore.Mvc (with controller), but not clean AspNetCore.Mvc.Core (without controller)?

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

@voronov-maxim as always, thanks. I just pulled the latest source and tested my query with an ICollection which included some some additional filter/expand clauses). I've said this timea and again, but I really appreciate the quick response.


Regarding the AspNetcore.Mvc vs AspNetCore.Mvc.Core, I'm not sure I'm following. Are you referring to using the middleware instead of using Mvc routing with the Controllers (like I am now)?

If so, one thing I'm still trying to figure out is the ability to apply additional clauses to an IQueryable after ODataToEntity has applied the OData query to it (hoping something like this is supported, I'm still reading through source and learning how OdataToEntity works).

For example, in OData/WebApi I can take in the queryOptions and applying them manually in the controller, instead of just applying a [Queryable] attribute. This returns a IQueryable<T> instance which I can continue to add .Where(), .Select(), joins, etc. I use this pattern for 2 cases currently.

1.) Add additional filters to the query based on the user (HttpContext.User.Identity) to restrict the type of results they can return (without using say row level filtering at the database level)

2.) Use the query to produce a different result, such as a data export (build an excel file, csv, etc).

With OData/WebApi, it would look something like this (although it's currently broken in the ASP.NET Core / OData 7.0.0 version)

[HttpGet]
public IActionResult Export(ODataQueryOptions<Employee> queryOptions)
{
    var query = queryOptions.ApplyTo(DbContext.Set<Employee>()) as IQueryable<Employee>;
    var exportQuery = query.Select(e => new EmployeeExport
    {
        Name = e.Name,
        // ...
    });

    // build Excel file, CSV, etc

    return Ok(exportQuery);
}

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

Oh and another reason is to have more control over the exposed routes. I'd like to be able to use [Route("/odata/something/[controller]")] where something changes based on the controller (to structure/organize the endpoints a little better) although last I tried it didn't work.

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

For example, in OData/WebApi I can take in the queryOptions and applying them manually in the controller, instead of just applying a [Queryable] attribute. This returns a IQueryable instance which I can continue to add .Where(), .Select(), joins, etc. I use this pattern for 2 cases currently.

You can overrride method ExecuteEnumerator in OeEfCoreDataAdapter and get IQueryable. But complex query with $select, $expand leads to the fact that TResult has type Tuple<Tuple<>,Tuple<>> and complicate to add .Where(), .Select(). Can try Global Query Filters

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

Hi @techniq
Would you please pay attention to the next release with many changes. It is based on branch 'groupjoin', eliminates subquery (N+1) and replaces them with 'LEFT JOIN'. Can your test this new version, please?

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

@voronov-maxim sounds great! I haven't moved to ODataToEntity just yet, as I'm dependent on a few features/workarounds I'm using with OData/WebApi needed to test more.

  • Support for non-root routes. For example /odata/generalLedger/Accounts and /odata/organizations/Departments. See my last few comments above.
  • Ability to apply an odata query but make additional modifications to the query (see OData/WebApi#1257 and mentioned in my last few comments as well).
  • Support for in operator (I just haven't tested this yet, and need to modify my odata-query library to produce the correct query (part of the OData 4.0.1 spec)
  • More general testing of queries I'm creating. My applications can leverage some pretty complicated nesting filtering / etc, and I just haven't had time yet to completely these these with ODataToEntity.

With all that said, I have an ODataToEntity branch that I will merge my latest into and give it a try when you cut the next NuGet release. I have to make some additional moifications when I do (change the routes form /odata/generalLedger/Accounts to /odata/Accounts, etc, but most of those occur in 1 spot).

Thanks again for the awesome library. I've already recently gotten more traction with the Microsoft folks regarding some of my open OData/WebApi issues and trying to see how fast they might be able to resolve them for me (although some have been open for close to a year now)

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

I can try solve two issues

Support for non-root routes
Support for in operator

To solve the third issue, make additional modifications to the query it may take a long time.

2.0.0-beta
Added support SourceLink for easy debugging

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

Hi @techniq
Support for non-root routes 44abdfb
Support for in operator b71ce24

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

@voronov-maxim I tried to build locally and use project references to use the latest commits (in groupjoin branch) as I have before in the past, but getting a build error. Not sure if it's due to the Sourcelink change. I'm on OSX.

/Users/techniq/.nuget/packages/microsoft.build.tasks.git/1.0.0-beta-63127-02/build/Microsoft.Build.Tasks.Git.targets(5,5): Error MSB4044: The "Microsoft.Build.Tasks.Git.GetRepositoryUrl" task was not given a value for the required parameter "Root". (MSB4044) (OdataToEntity)

image

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

I also left a comment here earlier by accident.

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

fyi, I renamed Directory.Build.targets to _Directory.Build.targets and restarted Visual Studio for Mac and I can build again. I'm manually apply the branch to my latest code (wasn't going to merge cleanly). Not sure I'll finish tonight, but I'll let you know once I do.

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

throwing an exception on startup

image

   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at OdataToEntity.ModelBuilder.OeEdmModelBuilder.BuildEdmModel() in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity/ModelBuilder/OeEdmModelBuilder.cs:line 102
   at OdataToEntity.EfCore.OeEfCoreDataAdapterExtension.BuildEdmModelFromEfCoreModel(OeDataAdapter dataAdapter) in /Users/techniq/Documents/Development/open-source/OdataToEntity/source/OdataToEntity.EfCore/OeEfCoreDataAdapterExtension.cs:line 18
   at Finance.Web.Startup.ConfigureServices(IServiceCollection services) in /Users/techniq/Documents/Development/sbcs-chh/app-finance/Finance.Web/Startup.cs:line 112
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.ConfigureServices(IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.Initialize()
   at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
   at Finance.Web.Program.Main(String[] args) in /Users/techniq/Documents/Development/sbcs-chh/app-finance/Finance.Web/Program.cs:line 10

Likely a modeling error in my large CommonDbContext (since I'm back to using it and not my smaller FinanceDbContext. I'm not sure I'll be able to dig in for a while to identity a small example

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

Ultimately CodingModel is an abstract class that also has an abstract generic IEntityTypeConfiguration<T> implementation that subclasses call

abstract public class CodingModelTypeConfiguration<T> : IEntityTypeConfiguration<T> where T : CodingModel
{
  ...
}

It appears to be some issue with this (works fine with my OData/WebApi setup), but I was able to work around the issue by adding public DbSet<CodingModel> CodingModels { get; set; } to my CommonDbContext.

I'm now getting exceptions thrown regarding my seed data (once again works fine in my other setup and not sure why it's a runtime issue as this is normally only involved when creating new migrations (dotnet ef migratoins add ...).

image

image

MaritialStatus is an example of a class that extends the abstract CodingModel and CodingModelTypeConfiguration<T> classes.

One note is within OnModelCreating() in our CommonDbContext, we call ApplyTypeConfigurations() extension method...
image

which scans the assembly for any IEntityTypeConfiguration implementors and applies those configurations to the modelBuilder.

image

At this point, it's probably going to be a while before I can get you much more details and try to work through this problem(s) to give you something you can reproduce.

from odatatoentity.

voronov-maxim avatar voronov-maxim commented on June 8, 2024

throwing an exception on startup

CodingModel throw KeyNotFoundException

OdataToEntity support abstract class Test model

from odatatoentity.

techniq avatar techniq commented on June 8, 2024

@voronov-maxim I commented out all my build.HasData(...) calls within subclasses of CodingModelTypeConfiguration<T> and I'm not back to this exception (even though I have public DbSet<CodingModel> CodingModels { get; set; } in my CommonDbContext)

image

from odatatoentity.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.