You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When using the Microsoft.EntityFrameworkCore.Cosmos database provider, there is an issue with setting a model property's type as JArray. Attempting to do so results in the following exception being thrown:
System.InvalidOperationException
HResult=0x80131509
Message=The 'JArray' property 'MyModel.Data' could not be mapped because the database provider does not support this type. Consider converting the property value to a type supported by the database using a value converter. See https://aka.ms/efcore-docs-value-converters for more information. Alternately, exclude the property from the model using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
As a workaround, modifiying MyDbContext.cs to include a ValueConverter stops the exception from being thrown
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
public class MyDbContext : DbContext
{
public MyDbContext() { }
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }
public virtual DbSet<MyModel>? MyModels { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyModel>()
.HasKey(o => o.Data);
modelBuilder.Entity<MyModel>() # Adding this block stops Exception from being thrown
.Property(e => e.Data)
.HasConversion(
v => v.ToString(),
v => JArray.Parse(v)
);
}
}
However, this is not the expected solution, since this way data is stored as a stringified json instead of an actual json array. Cosmosdb supports storing actual json objects/arrays.
Also changing the object type to JObject doesn't throw the error, and I'm able to save it properly as a json object in cosmosdb, which leads me to think that it is a supported datatype. So why is the JObject supported and not the JArray, although they come from the same library?
Include stack traces
System.InvalidOperationException
HResult=0x80131509
Message=The 'JArray' property 'MyModel.Data' could not be mapped because the database provider does not support this type. Consider converting the property value to a type supported by the database using a value converter. See https://aka.ms/efcore-docs-value-converters for more information. Alternately, exclude the property from the model using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
Source=Microsoft.EntityFrameworkCore
StackTrace:
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ThrowPropertyNotMappedException(String propertyType, IConventionEntityType entityType, IConventionProperty unmappedProperty) in /_/src/EFCore/Infrastructure/ModelValidator.cs:line 275
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidatePropertyMapping(IModel model, IDiagnosticsLogger`1 logger) in /_/src/EFCore/Infrastructure/ModelValidator.cs:line 153
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger) in /_/src/EFCore/Infrastructure/ModelValidator.cs:line 49
at Microsoft.EntityFrameworkCore.Cosmos.Infrastructure.Internal.CosmosModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.Initialize(IModel model, Boolean designTime, IDiagnosticsLogger`1 validationLogger) in /_/src/EFCore/Infrastructure/ModelRuntimeInitializer.cs:line 87
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, ModelCreationDependencies modelCreationDependencies, Boolean designTime) in /_/src/EFCore/Infrastructure/ModelSource.cs:line 80
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel(Boolean designTime) in /_/src/EFCore/Internal/DbContextServices.cs:line 86
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model() in /_/src/EFCore/Internal/DbContextServices.cs:line 113
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, 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.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, 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.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, 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.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, 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.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, 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.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, 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__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) in /_/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs:line 46
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) in /_/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs:line 63
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() in /_/src/EFCore/DbContext.cs:line 467
at Microsoft.EntityFrameworkCore.DbContext.get_ContextServices() in /_/src/EFCore/DbContext.cs:line 447
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() in /_/src/EFCore/DbContext.cs:line 467
at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies.get_StateManager() in /_/src/EFCore/DbContext.cs:line 217
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.EntryWithoutDetectChanges(TEntity entity) in /_/src/EFCore/Internal/InternalDbSet.cs:line 539
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.<AddAsync>d__19.MoveNext() in /_/src/EFCore/Internal/InternalDbSet.cs:line 206
at System.Threading.Tasks.ValueTask`1.get_Result() in /_/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ValueTask.cs:line 785
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult() in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValueTaskAwaiter.cs:line 126
at Program.<RunAsync>d__1.MoveNext() in C:\Users\GPATACA\source\WebApplication1\Program.cs:line 36
at Program.<Main>d__0.MoveNext() in C:\Users\GPATACA\source\WebApplication1\Program.cs:line 21
at Program.<Main>(String[] args)
Include provider and version information
EF Core version: 7.0.9
Database provider: Microsoft.EntityFrameworkCore.Cosmos
Target framework: .NET 6.0
Operating system: Windows 11
IDE: Visual Studio 2022 17.6.5
The text was updated successfully, but these errors were encountered:
@SupernectarJObject is supported as an implementation detail and may not be supported in future releases. What is your motivation for using JArray or JObject properties in your entity types?
@ajcvickers By excluding support for JArray or JObject, we are essentially limiting the flexibility for users to store objects containing custom fields. This limitation forces developers to create a separate model for each potential body input the user might provide, which is clearly impractical and not a viable solution.
The current support generally indeed requires a strongly-typed model. We do have plans to allow for weakly-typed/dynamic models as you'd like. However, note that if that's done via JArray/JObject, that ties you to the specific JSON package used by the provider - that's currently Newtonsoft.Json but should switch to System.Text.Json at some point (and that would be a breaking change). Because of this, simply allow non-JSON .NET Dictionary/List is probably a better approach here.
File a bug
When using the
Microsoft.EntityFrameworkCore.Cosmos
database provider, there is an issue with setting a model property's type as JArray. Attempting to do so results in the following exception being thrown:Include your code
To reproduce this bug, you can clone this repo https://github.com/Supernectar/EFCosmosJArrayBug.git. Simply building and running the project should trigger the exception mentioned above.
As a workaround, modifiying MyDbContext.cs to include a ValueConverter stops the exception from being thrown
However, this is not the expected solution, since this way data is stored as a stringified json instead of an actual json array. Cosmosdb supports storing actual json objects/arrays.
Also changing the object type to JObject doesn't throw the error, and I'm able to save it properly as a json object in cosmosdb, which leads me to think that it is a supported datatype. So why is the JObject supported and not the JArray, although they come from the same library?
Include stack traces
Include provider and version information
EF Core version: 7.0.9
Database provider: Microsoft.EntityFrameworkCore.Cosmos
Target framework: .NET 6.0
Operating system: Windows 11
IDE: Visual Studio 2022 17.6.5
The text was updated successfully, but these errors were encountered: