Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Json: error when trying to materialize json entity with nullable property that is null in the json string - should materialize the property as null instead #34293

Closed
r-Larch opened this issue Jul 26, 2024 · 3 comments · Fixed by #35040
Assignees
Labels
area-json area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Milestone

Comments

@r-Larch
Copy link

r-Larch commented Jul 26, 2024

Maybe a regression of #29219

Materializing a JSON entity with null property results in an error even if the target model allows null.
Expected to materialize the property as null instead.

var error2 = await db.LawCategories
    .AsNoTracking()
    .Where(_ => _.Id == 2)
    .Select(_ => new ModelDto(_.Id, _.Meta.Release))
    .FirstOrDefaultAsync(token); // error: System.InvalidOperationException: Entity LawRelease is required but the JSON element containing it is null.
    
public record ModelDto(int Id, LawRelease? Release);
System.InvalidOperationException: Entity LawRelease is required but the JSON element containing it is null.
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.MaterializeJsonEntity[TEntity](QueryContext queryContext, Object[] keyPropertyValues, JsonReaderData jsonReaderData, Boolean nullable, Func`4 shaper)
   at lambda_method697(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)

Entity Definition:

public class LawCategory {
    public int Id { get; set; }
    // ... props
    public LawCategoryMeta Meta { get; set; } = null!;

    // ... navigation
}

public class LawCategoryMeta {
    public LawRelease? Release { get; set; }
}

public class LawCategoryConfiguration : IEntityTypeConfiguration<LawCategory> {
    public void Configure(EntityTypeBuilder<LawCategory> builder) {
        builder.OwnsOne(_ => _.Meta, _ => {
            _.ToJson();
            _.OwnsOne(_ => _.Release);
        });
        // ... more
    }
}

Data

Id Meta Note
2 {"Release": null} error in all cases
19 {"Release": {"Date": "2022-10-10", "Number": 149, "Source": "Lgs."}} works in all cases

Example Code to show error

var works = await db.LawCategories
    .AsNoTracking()
    .Where(_ => _.Id == 19)
    .Select(_ => _.Meta.Release)
    .FirstOrDefaultAsync(token); // works

var error1 = await db.LawCategories
    .AsNoTracking()
    .Where(_ => _.Id == 2)
    .Select(_ => _.Meta.Release)
    .FirstOrDefaultAsync(token); // error: System.InvalidOperationException: Entity LawRelease is required but the JSON element containing it is null.
    
var error2 = await db.LawCategories
    .AsNoTracking()
    .Where(_ => _.Id == 2)
    .Select(_ => new ModelDto(_.Id, _.Meta.Release))
    .FirstOrDefaultAsync(token); // error: System.InvalidOperationException: Entity LawRelease is required but the JSON element containing it is null.
    
public record ModelDto(int Id, LawRelease? Release);

Provider and version information

EF Core version:
Microsoft.EntityFrameworkCore v8.0.7
Database provider: Npgsql.EntityFrameworkCore.PostgreSQL v8.0.4
Target framework: .NET 8.0
Operating system: Windows
IDE: Microsoft Visual Studio Community 2022 (64-bit) Version 17.10.4

@dashiell-zhang
Copy link

dashiell-zhang commented Aug 21, 2024

Entity OrganizationData is required but the JSON element containing it is null

I also encountered this problem today

public OrganizationData? Organization { get; set; }

{
  "User": {
    "Gender": 1,
    "IsInJob": false,
    "UserName": "xiaodong",
    "TravelLevel": "ygzj-1",
    "OrganizationCode": "XXB",
    "SettlementEntityCode": "xxB"
  },
  "Organization": null,
  "SettlementEntity": null
}

Normal operation:
var sss = db.TImportData.AsNoTracking().ToList();


There is a bug:
var sss1 = db.TImportData.AsNoTracking().Select(t => t.Data).ToList();

@dashiell-zhang
Copy link

@roji From what we have observed so far, if you query directly against the table, there is no problem, but if you query against a new dto, there will be a problem.

@maumar
Copy link
Contributor

maumar commented Nov 4, 2024

The problem is we were incorrectly computing the nullability of json reference - using navigation.ForeignKey.IsRequired rather than navigation.ForeignKey.IsRequiredDependent

maumar added a commit that referenced this issue Nov 5, 2024
…th nullable property that is null in the json string - should materialize the property as null instead

Problem was that when computing nullability of a JSON entity we were using faulty logic - checking if the foreign key is required, rather than if its required dependent. This lead to optional entities being incorrectly marked as required and cause validation error when JSON contained null.

Fixes #34293
@maumar maumar added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Nov 5, 2024
@maumar maumar added this to the 10.0.0 milestone Nov 5, 2024
maumar added a commit that referenced this issue Nov 5, 2024
…th nullable property that is null in the json string - should materialize the property as null instead

Problem was that when computing nullability of a JSON entity we were using faulty logic - checking if the foreign key is required, rather than if its required dependent. This lead to optional entities being incorrectly marked as required and cause validation error when JSON contained null.

Fixes #34293
@maumar maumar closed this as completed in 612ccbf Nov 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-json area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Projects
None yet
6 participants