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

InvalidOperationException with JSON columns and owned entities on update #32621

Closed
GHMeyer0 opened this issue Dec 15, 2023 · 6 comments
Closed

Comments

@GHMeyer0
Copy link

Description

I'm encountering an InvalidOperationException when trying to update an entity that contains a JSON column mapping to owned entities. The issue arises specifically with the Acoes entity within the ParametrosDaReguaDeAcao owned entity. The error suggests an issue with the shadow key property of Acoes.Id.

Code

public class ReguaDeAcao
{
    public Guid Id { get; set; }
    public Guid ClienteId { get; set; }
    public DateTime CriadoEm { get; set; } = DateTime.UtcNow;
    public DateTime? AtualizadoEm { get; set; }
    public Guid UsuarioId { get; set; }
    public required string Nome { get; set; }
    public bool Padrao { get; set; }
    public bool Ativo { get; set; }
    public required ParametrosDaReguaDeAcao Parametros { get; set; }

    public class ParametrosDaReguaDeAcao
    {
        public List<Acoes> Acoes { get; set; } = new();
    }

    public class Acoes
    {
        public int QuantidadeDeDias { get; set; }
        public Sms? Sms { get; set; }
        public Email? Email { get; set; }
    }
}
  modelBuilder.Entity<ReguaDeAcao>()
    .OwnsOne(regua => regua.Parametros, ownedNavigationBuilder =>
        {
            ownedNavigationBuilder.ToJson();
            ownedNavigationBuilder.OwnsMany(
                parametros => parametros.Acoes, ownedOwnedNavigationBuilder =>
                {
                    ownedOwnedNavigationBuilder.OwnsOne(acao => acao.Sms);
                    ownedOwnedNavigationBuilder.OwnsOne(acao => acao.Email);
                });
        });

stack traces & logs

[08:40:28 DBG] Context 'SqlContext' started tracking 'ReguaDeAcao' entity with key '{Id: 300d59e4-1ab0-4952-b373-8e34146fc679}'.
[08:40:28 DBG] Context 'SqlContext' started tracking 'ParametrosDaReguaDeAcao' entity with key '{ReguaDeAcaoId: 300d59e4-1ab0-4952-b373-8e34146fc679}'.
[08:40:28 DBG] 'SqlContext' generated temporary value '-2147482647' for the property 'Acoes.Id'.
[08:40:28 DBG] Context 'SqlContext' started tracking 'Acoes' entity with key '{ParametrosDaReguaDeAcaoReguaDeAcaoId: 300d59e4-1ab0-4952-b373-8e34146fc679, Id: -2147482647}'.
[08:40:28 DBG] Context 'SqlContext' started tracking 'Email' entity with key '{AcoesParametrosDaReguaDeAcaoReguaDeAcaoId: 300d59e4-1ab0-4952-b373-8e34146fc679, AcoesId: -2147482647}'.
[08:40:28 DBG] Context 'SqlContext' started tracking 'Sms' entity with key '{AcoesParametrosDaReguaDeCobrancaReguaDeCobrancaId: 300d59e4-1ab0-4952-b373-8e34146fc679, AcoesId: -2147482647}'.
[08:40:32 DBG] DetectChanges starting for 'SqlContext'.
[08:40:32 DBG] DetectChanges completed for 'SqlContext'.
[08:40:32 DBG] SaveChanges starting for 'SqlContext'.
[08:40:32 DBG] DetectChanges starting for 'SqlContext'.
[08:40:32 DBG] DetectChanges completed for 'SqlContext'.
[08:40:32 ERR] An exception occurred in the database while saving changes for context type 'Tiino.Cobranca.Infraestructure.SqlContext'.
[08:40:32 ERR] An exception occurred in the database while saving changes for context type 'Tiino.Infraestructure.SqlContext'.
System.InvalidOperationException: The value of shadow key property 'Acoes.Id' is unknown when attempting to save changes. This is because shadow property values cannot be preserved when the entity is not being tracked. Consider adding the property to the entity's .NET type. See https://aka.ms/efcore-docs-owned-collections for more information.
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.<PrepareToSave>g__CheckForUnknownKey|111_0(IProperty property, <>c__DisplayClass111_0&)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.PrepareToSave()
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.GetEntriesToSave(Boolean cascadeChanges)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
System.InvalidOperationException: The value of shadow key property 'Acoes.Id' is unknown when attempting to save changes. This is because shadow property values cannot be preserved when the entity is not being tracked. Consider adding the property to the entity's .NET type. See https://aka.ms/efcore-docs-owned-collections for more information.
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.<PrepareToSave>g__CheckForUnknownKey|111_0(IProperty property, <>c__DisplayClass111_0&)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.PrepareToSave()
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.GetEntriesToSave(Boolean cascadeChanges)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)

Include provider and version information

EF Core version: 8.0.3
Database provider: Npgsql.EntityFrameworkCore.PostgreSQL
Target framework: .NET 8.0
Operating system: Linux
IDE: Visual Studio 2022 17.4

Additional Context

I am attempting to update an entity with a JSON column (Parametros) that includes a collection of owned entities (Acoes). This issue occurs during the update operation, where the shadow key property Acoes.Id seems to be causing trouble. Any guidance or suggestions on how to address this issue would be greatly appreciated.

@ajcvickers
Copy link
Contributor

This issue is lacking enough information for us to be able to fully understand what is happening. Please attach a small, runnable project or post a small, runnable code listing that reproduces what you are seeing so that we can investigate.

@GHMeyer0
Copy link
Author

Hi @ajcvickers, I created an example project to reproduce the error, I published it on my GitHub

https://github.com/GHMeyer0/InvalidOperation

You need to make a POST with this information

curl -X 'POST' \
  'https://localhost:32770/api/ActionRules' \
  -H 'accept: text/plain' \
  -H 'Content-Type: application/json' \
  -d '{
  "id": "829f7302-235d-4060-b0d2-6349995fbaa6",
  "description": "string",
  "creationDate": "2023-12-18T15:30:24.893Z",
  "parameters": {
    "actions": [
      {
        "email": {
          "message": "string"
        },
        "sms": {
          "message": "string"
        }
      }
    ]
  }
}'

Then make a PATCH with these changes

curl -X 'PATCH' \
  'https://localhost:32770/api/ActionRules/829f7302-235d-4060-b0d2-6349995fbaa6' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '[
    {
        "op": "add",
        "path": "/parameters/actions/1",
        "value": {
            "email": {
                "message": "string"
            },
            "sms": {
                "message": "string"
            }
        }
    }
]'

@ajcvickers
Copy link
Contributor

@GHMeyer0 The link seems to be broken.

@GHMeyer0
Copy link
Author

GHMeyer0 commented Jan 3, 2024

@ajcvickers, sorry, I had published the repository with private visibility, I already changed it to public
https://github.com/GHMeyer0/InvalidOperation

@ajcvickers
Copy link
Contributor

Note for triage: I believe this is currently by-design because we don't know the key values of the synthesized keys for items of an owned collection. I'm not sure if we should/can do anything better here. For non-JSON, the appropriate fix would be to add a non-synthesized key, but I don't think that works for JSON. This kind of scenario will be better handled by collections of complex types.

@ajcvickers
Copy link
Contributor

Duplicate of #28594

@ajcvickers ajcvickers marked this as a duplicate of #28594 Jan 22, 2024
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Jan 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants