question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

JsonDocument type property and InMemoryDatabase provider

See original GitHub issue

Notice: probably it is more InMemoryDatabase provider issue, but it is related to Npgsql driver.

Steps to reproduce

If you have free form json field something like

public JsonDocument ProviderData { get; set; }

It works fine at runtime, as Npgsql driver somehow handles it. Now if I wish to unit test this with:

 context = new MyDbContext(new DbContextOptionsBuilder<MyDbContext>()
                .UseInMemoryDatabase("My")
                .Options);

It fails with: No suitable constructor found for entity type ‘JsonDocument’.

The issue

I can not unit test models that are valid in Npgsql with InMemoryDatabase.

As a workaround, I would be fine to ignore that property in unit tests or augument DbContext in unit tests to avoid this problem, but currently have no ideas how.

Full exception trace:

System.InvalidOperationException : No suitable constructor found for entity type 'JsonDocument'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'utf8Json', 'parsedData', 'extraRentedBytes', 'isDisposable' in 'JsonDocument(ReadOnlyMemory<byte> utf8Json, MetadataDb parsedData, byte[] extraRentedBytes, bool isDisposable)'.
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.ConstructorBindingConvention.ProcessModelFinalized(IConventionModelBuilder modelBuilder, IConventionContext`1 context)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalized(IConventionModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalized(IConventionModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
   at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.EntryWithoutDetectChanges[TEntity](TEntity entity)
   at Microsoft.EntityFrameworkCore.DbContext.SetEntityState[TEntity](TEntity entity, EntityState entityState)
   at Microsoft.EntityFrameworkCore.DbContext.Add[TEntity](TEntity entity)
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Add(TEntity entity)
   at Api.Test.Tests.Setup() in C:\work\api\test\Api.Test

Further technical details

Npgsql version: 3.1.2

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

11reactions
dziedriuscommented, Feb 27, 2023

As usually happens, five minutes after submitting issue you come up with solution 😃

I was able to workaround the issue by extending DbContext class in unit tests:

 public class UnitTestMyDbContext : MyDbContext
    {
        public UnitTestMyDbContext(DbContextOptions options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MyEntity>().Property(p => p.SomeWellDefinedJsonProperty)
                .HasConversion(
                    v => JsonConvert.SerializeObject(v),
                    v => JsonConvert.DeserializeObject<WellDefinedJsonProperty>(v));
       
            modelBuilder.Entity<MyEntity>().Property(p => p.ProviderData)
                .HasConversion(
                    v => JsonDocumentToString(v),
                    v => JsonDocument.Parse(v, new JsonDocumentOptions()));      
        }

        private static string JsonDocumentToString(JsonDocument document)
        {
            using (var stream = new MemoryStream())
            {
                var writer = new Utf8JsonWriter(stream, new JsonWriterOptions {Indented = true});
                document.WriteTo(writer);
                writer.Flush();
                return Encoding.UTF8.GetString(stream.ToArray());
            }
        }
    }

It could be useful addition to documentation.

1reaction
rahul-s-bhattcommented, Feb 27, 2023

Hi @dziedrius thank you and sorry for troubling you. But I have fixed that by adding :

modelbuidler.Ignore<JsonDocument>

Thank you once again 👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

JsonDocument type property and InMemoryDatabase ...
It fails with: No suitable constructor found for entity type 'JsonDocument'. The issue. I can not unit test models that are valid in...
Read more >
Entity Framework Core exception: No suitable constructor ...
JsonDocument class doesn't have any properties, so if you want to use JsonDocument as a common Net class, you will have at first...
Read more >
Announcing Entity Framework Core 7 RC2: JSON Columns
JSON columns allow relational databases to take on some of the characteristics of document databases, creating a useful hybrid between the two.
Read more >
Tips for Building Tests with EF Core and Its InMemory ...
I'm using SQL Server again and I've stored the connection string in the ASP.NET Core appsettings.json file under the name productionDb. The service...
Read more >
Connect to InMemory Database with Entity Framework Core
Tutorial built with .NET 6.0. This post shows how to connect a .NET 6 API to an InMemory database for testing with Entity...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found