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

Error Updating a Json Column in an Entity not Tracked #31438

Closed
danielscatigno-ncpc opened this issue Aug 9, 2023 · 2 comments
Closed

Error Updating a Json Column in an Entity not Tracked #31438

danielscatigno-ncpc opened this issue Aug 9, 2023 · 2 comments

Comments

@danielscatigno-ncpc
Copy link

EF Core version: 7.0.9
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 7.0
Operating system: IDE: Windows - Visual Code

I'm getting the following exception:

Exception has occurred: CLR/System.InvalidOperationException
An exception of type 'System.InvalidOperationException' occurred in NCPC.Infra.dll but was not handled in user code: 'The value of shadow key property 'InformacaoCoordenada.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 NCPC.Infra.UnitOfWork.SaveChanges() in C:\Projetos\NCPC\NCPC.Infra\UnitOfWork.cs:line 123
at CapturaXML.Test.UnitTest1.ShouldUpdateTipoCobranca() in c:\Projetos\NC\CapturaXML\CapturaXML.Test\UnitTest1.cs:line 114
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)

The case is that I have an entity with a Json Column mapped
When I try to update the Entity (without tracking) it throws the error

I'm mapping the column with :

   public class TipoCobrancaMap : IEntityTypeConfiguration<TipoCobranca>
   {
      public void Configure(EntityTypeBuilder<TipoCobranca> builder)
      {
         builder.HasKey(x => x.Id);
         builder.Property(x => x.Nome).IsRequired().HasMaxLength(100);
         builder.Property(x => x.IsPDF);
         builder.Property(x => x.Linguagem);         
         builder.Property(x => x.HistoricoDescricao).HasMaxLength(1000);
         builder.Property(x => x.ArquivoExemplo);
         builder.Property(x => x.IdentificadoresContaEsperado)
            .HasConversion(v => string.Join(';', v), v => v.Split(';', StringSplitOptions.None).ToList());

         builder.OwnsMany(x => x.Identificadores, navigationBuilder =>
         {
            navigationBuilder.ToJson();            
            //navigationBuilder.Property(x=>x.TipoDado).HasConversion(v=>v.ToString(),v=> Type.GetType(v));            
            navigationBuilder.Property(x=>x.Tipo).HasConversion<string>();
         });

         builder.HasMany(x => x.Contas).WithMany(x => x.TiposCobranca).UsingEntity("ContaTipoCobranca",
            l => l.HasOne(typeof(Conta)).WithMany().HasForeignKey("ContaId").HasPrincipalKey(nameof(Conta.IdConta)),
            r => r.HasOne(typeof(TipoCobranca)).WithMany().HasForeignKey("TipoCobrancaId").HasPrincipalKey(nameof(TipoCobranca.Id)),
            j => j.HasKey("TipoCobrancaId", "ContaId"));

      }
   }

and I have written the following test:


   [Fact]
   public void ShouldUpdateTipoCobranca()
   {
      var context = new ContextProvider();
      var uow = context.ServiceProvider.GetRequiredService<IUnitOfWork>();
      var mapper = context.ServiceProvider.GetRequiredService<IMapper>();
      var tipoCobrancaRepo = uow.GetRepository<TipoCobrancaRepository>();
      var tipoCobranca = tipoCobrancaRepo.GetAll().AsNoTracking().First();
      var viewModel = mapper.Map<TipoCobrancaViewModel>(tipoCobranca);
      tipoCobranca = mapper.Map<TipoCobranca>(viewModel);
      tipoCobrancaRepo.Attatch(tipoCobranca);
      tipoCobranca.Identificadores.First().Width+=1;
      tipoCobrancaRepo.Update(tipoCobranca);
      uow.SaveChanges();
      Assert.NotNull(tipoCobranca);
   }

I've already tried to create a Key Property but I get another error

Any thoughts?

@ajcvickers
Copy link
Contributor

Note for triage: is there any way to currently achieve this when the owned collection is mapped to JSON? The normal guidance is to explicitly declare the key, but I think that is blocked when using JSON mapping.

@ajcvickers
Copy link
Contributor

@danielscatigno-ncpc We discussed this, and you could try using DbSet.Add first to re-generate keys. But in general, collections of owned types without keys are not easy to use in disconnected scenarios, so we really need to allow a key to be specified, or support collections of complex types.

@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Sep 20, 2023
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