OData / OData/RESTier

Problems adding Entities / Related Entities

Open
#759 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
481
Forks
136
PR merge metrics
No merged PRs in 30d

Description

Short summary (3-5 sentences) describing the issue.
Adding new Entity with Savechengesoption.Batch) with related Entit(ies) from Dataservicecollection does not work as expected

Assemblies affected

For Information:
Project references server:

TargetFramework>net8.0 UserSecretsId>0747c9f0-3a8d-4969-a360-a7dc2e7f8489 PlatformTarget>x64

"IBM.EntityFrameworkCore" Version="8.0.0.200" />
"Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.16" />
"Microsoft.AspNetCore.DataProtection" Version="7.0.2" />
"Microsoft.EntityFrameworkCore.Design" Version="8.0.5">

"Microsoft.Extensions.Configuration" Version="7.0.0" />
"Microsoft.OData.ModelBuilder" Version="1.0.9" />
"Microsoft.Restier.AspNetCore" Version="1.1.0" />
"Microsoft.Restier.Core" Version="1.1.0" />
"Microsoft.Restier.EntityFrameworkCore" Version="1.1.0" />
"Newtonsoft.Json" Version="13.0.3" />
Swashbuckle.AspNetCore" Version="6.5.0" />

Reproduce steps

I want to add new Element with related elements.
relation is 1:n

car key is nr
box key is car_nr, nr

the described issue is on

DataServiceCollection cars = new DataServiceCollection(context);
car newcar = new car() { nr = "test1", such = "test1",name="Test",kennzeichen="hallo" };

newcar.boxes.Add(new box() {car_nr="test1", nr = 1, dompos = 1,art_nr=""});

cars.Add(newcar);

context.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset); // causes exception

Expected result

In WCF Odata V3 with Savechanges(Batch) this works as expected. New car is created with boxes. No need to enter car_id in every box created

When I use restier 1 or 1.1 i have to use
context.SaveChanges(); // works but causes single requests and neds car_id in box . No transaction around request.

Actual result

when I use cont.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset)
this results in a strange Error message
Stacktrace:
Microsoft.OData.Core.dll!Microsoft.OData.UriParser.ODataPathParser.CreateDynamicPathSegment(Microsoft.OData.UriParser.ODataPathSegment previous, string identifier, string parenthesisExpression) Unbekannt
Microsoft.OData.Core.dll!Microsoft.OData.UriParser.ODataPathParser.CreateFirstSegment(string segmentText) Unbekannt
Microsoft.OData.Core.dll!Microsoft.OData.UriParser.ODataPathParser.ParsePath(System.Collections.Generic.ICollection segments) Unbekannt
Microsoft.OData.Core.dll!Microsoft.OData.UriParser.ODataPathFactory.BindPath(System.Collections.Generic.ICollection segments, Microsoft.OData.UriParser.ODataUriParserConfiguration configuration) Unbekannt
Microsoft.OData.Core.dll!Microsoft.OData.UriParser.ODataUriParser.ParsePathImplementation() Unbekannt
Microsoft.OData.Core.dll!Microsoft.OData.UriParser.ODataUriParser.Initialize() Unbekannt
Microsoft.OData.Core.dll!Microsoft.OData.UriParser.ODataUriParser.ParsePath() Unbekannt
Microsoft.AspNetCore.OData.dll!Microsoft.AspNet.OData.Routing.DefaultODataPathHandler.Parse(string serviceRoot, string odataPath, System.IServiceProvider requestContainer, bool template) Unbekannt
Microsoft.AspNetCore.OData.dll!Microsoft.AspNet.OData.Routing.DefaultODataPathHandler.Parse(string serviceRoot, string odataPath, System.IServiceProvider requestContainer) Unbekannt
Microsoft.AspNetCore.OData.dll!Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint.GetODataPath(string oDataPathString, string uriPathString, string queryString, System.Func<System.IServiceProvider> requestContainerFactory) Unbekannt
Microsoft.AspNetCore.OData.dll!Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint.Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) Unbekannt
Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Routing.RouteConstraintMatcher.Match(System.Collections.Generic.IDictionary<string, Microsoft.AspNetCore.Routing.IRouteConstraint> constraints, Microsoft.AspNetCore.Routing.RouteValueDictionary routeValues, Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, Microsoft.AspNetCore.Routing.RouteDirection routeDirection, Microsoft.Extensions.Logging.ILogger logger) Unbekannt
Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Routing.RouteBase.RouteAsync(Microsoft.AspNetCore.Routing.RouteContext context) Unbekannt
Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Routing.RouteCollection.RouteAsync(Microsoft.AspNetCore.Routing.RouteContext context) Unbekannt
Microsoft.AspNetCore.Routing.dll!Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext httpContext) Unbekannt

Microsoft.Restier.AspNetCore.dll!Microsoft.Restier.AspNetCore.Middleware.ODataBatchHttpContextFixerMiddleware.InvokeAsync(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Http.IHttpContextAccessor contextAccessor) Zeile 21 C#
Microsoft.AspNetCore.OData.dll!Microsoft.AspNet.OData.Batch.ODataBatchRequestItem.SendRequestAsync(Microsoft.AspNetCore.Http.RequestDelegate handler, Microsoft.AspNetCore.Http.HttpContext context, System.Collections.Generic.IDictionary<string, string> contentIdToLocationMapping) Unbekannt
Microsoft.Restier.AspNetCore.dll!Microsoft.Restier.AspNetCore.Batch.RestierBatchChangeSetRequestItem.SendRequestAsync(Microsoft.AspNetCore.Http.RequestDelegate handler) Zeile 38 C#
Microsoft.AspNetCore.OData.dll!Microsoft.AspNet.OData.Batch.DefaultODataBatchHandler.ExecuteRequestMessagesAsync(System.Collections.Generic.IEnumerable<Microsoft.AspNet.OData.Batch.ODataBatchRequestItem> requests, Microsoft.AspNetCore.Http.RequestDelegate handler) Unbekannt
Microsoft.AspNetCore.OData.dll!Microsoft.AspNet.OData.Batch.DefaultODataBatchHandler.ProcessBatchAsync(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Http.RequestDelegate nextHandler) Unbekannt

in OdataUtriParser the Uri which has to be pasrsed is :http://192.168.0.87:5000/$121/boxes
I think when handling the call as a Batch the batch should be splitted in the single operations but somehow this gets lost during the call.
Do yo have a hint ?

in OdataPathParser this stops with
private void CreateDynamicPathSegment(ODataPathSegment previous, string identifier, string parenthesisExpression)
{
if (configuration.ParseDynamicPathSegmentFunc != null)
{
ICollection collection = configuration.ParseDynamicPathSegmentFunc(previous, identifier, parenthesisExpression);
parsedSegments.AddRange(collection);
return;
}
if (previous == null)
{
>>>>>> here throw ExceptionUtil.CreateResourceNotFoundError(identifier); >>> identifier is $121
}

Expected Behavior : Correct Insert in Batch with single changeset
For using this as a successor to wcf odata it is essential for me to be able to update Contexts with savechanges Batch handling in a Transaction.

Additional details

Aditionally

  1. Problem when related entity does not have id of master Entity
    In the box Entities I have to add the kfz nr, otherwise the insert will not happen. Neither with context.Savechanges() nor with
    context.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset)

If I enter Null as Kfz Nr I get an Exception that the column does not allow null values,
If I Enter an Empty string, Just a new Item with Empty kfz_nr is created.

Expected Bahavior: Savechanges should work like in Wcf Odata V3 with no need to add number of Master Entity in the related entity .

  1. Next problem with entity references
    When the entity box contains an object reference to the car entity this causes an exception that the payload should not contain navigation properties

Expected behavior: References within the object structure should not cause problems in updating object graphs

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the BatchWithSingleChangeset request using the provided car and box entities, then trace Microsoft.Restier.AspNetCore.Middleware.ODataBatchHttpContextFixerMiddleware.InvokeAsync into ODataPathParser.CreateDynamicPathSegment. Compare the generated $121/boxes path with the expected batch operations and inspect the related-entity and navigation-property failures. Done means the batch insert, relationship handling, and object references work without manually supplying the master key.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, backend
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.