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
I'm attempting to use the new JSON column functionality for storing translations in a JSON column, as opposed to storing the in a separate table. My first attempt was to store translations in a Dictionary<byte, string> where the byte would be the language ID and a string the value, but that currently doesn't work, as described in #30707.
So I have the following class that is being mapped to a JSON column.
SELECT [c].[Id], [c].[Code], JSON_VALUE([c].[NameTranslation], '$.CZ') AS [Name]
FROM [flat].[Country] AS [c]
Is there a way to translate my GetValueOrDefault method to SQL so it would also grab the property directly in SQL using JSONVALUE?
Also on a side note, I thought that whenever you use a projection to a non-tracked object in a query, the query is automatically a non-tracking once, but I'm getting the following exception when I omit the AsNoTracking() call on those example queries:
System.InvalidOperationException: 'JSON entity or collection can't be projected directly in a tracked query. Either disable tracking by using 'AsNoTracking' method or project the owner entity instead.'
Repro
Here's the full code to repro (requires a connection string to a running SQL server instance):
usingMicrosoft.EntityFrameworkCore;usingMicrosoft.EntityFrameworkCore.Metadata.Builders;usingMicrosoft.Extensions.Logging;namespaceJsonColumnTranslationsDemo;publicstaticclassFlatDemo{publicstaticvoidRun(stringconnectionString){varoptions=newDbContextOptionsBuilder<AppDbContext>().UseSqlServer(connectionString).LogTo(Console.WriteLine,LogLevel.Information).Options;vardbContext=newAppDbContext(options);dbContext.Database.EnsureDeleted();dbContext.Database.EnsureCreated();varczechia=newCountry{Code="CZ",NameTranslation=Translation.Create("Česko","Czechia"),};varjapan=newCountry{Code="JP",NameTranslation=Translation.Create("Japonsko","Japan"),};dbContext.Add(czechia);dbContext.Add(japan);dbContext.SaveChanges();// NOTE: this grabs the entire NameTranslation JSON column and extracts the CZ value in memoryvarlocalizedCountries=dbContext.Countries// System.InvalidOperationException: 'JSON entity or collection can't be projected directly in a tracked query. Either disable tracking by using 'AsNoTracking' method or project the owner entity instead.'.AsNoTracking().Select(c =>newCountryResponse{Id=c.Id,Code=c.Code,Name=c.NameTranslation.GetValueOrDefault(Language.CZ)!,}).ToList();foreach(varlocalizedCountryinlocalizedCountries){Console.WriteLine($"Id: {localizedCountry.Id}, Code: {localizedCountry.Code}, Name: {localizedCountry.Name}");}}publicclassAppDbContext:DbContext{publicDbSet<Country>Countries{get;set;}publicAppDbContext(DbContextOptions<AppDbContext>options):base(options){}protectedoverridevoidOnModelCreating(ModelBuildermodelBuilder){modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);}}publicclassCountry{publicintId{get;set;}publicstringCode{get;set;}publicTranslationNameTranslation{get;set;}}publicclassCountryResponse{publicintId{get;set;}publicstringCode{get;set;}publicstringName{get;set;}}publicenumLanguage:byte{CZ=1,EN=2,}publicclassTranslation{publicstringCZ{get;set;}publicstringEN{get;set;}publicstring?GetValueOrDefault(Languagelanguage)=>languageswitch{Language.CZ=>CZ,Language.EN=>EN,
_ =>null,};publicstaticTranslationCreate(stringcz,stringen)=>new(){CZ=cz,EN=en,};}publicclassCountryConfiguration:IEntityTypeConfiguration<Country>{publicvoidConfigure(EntityTypeBuilder<Country>builder){builder.ToTable(nameof(Country),"flat");builder.OwnsOne(c =>c.NameTranslation, translationBuilder =>{translationBuilder.ToJson();});}}}
Provider and version information
EF Core version: 8.0.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 8.0
Operating system: Windows 10 22H2
IDE: Visual Studio 2022 17.8.1
The text was updated successfully, but these errors were encountered:
Is there a way to translate my GetValueOrDefault method to SQL so it would also grab the property directly in SQL using JSONVALUE?
The GetValueOrDefault method is opaque to EF Core. There is no way for EF to know which properties of the NameTranslation object will be used, so the entire object must be created.
Also on a side note, I thought that whenever you use a projection to a non-tracked object in a query, the query is automatically a non-tracking once, but I'm getting the following exception when I omit the AsNoTracking() call on those example queries:
This is by-design. The idea is that people might not realize than projected owned entity types are not tracked by default, while projected non-owned entity types are.
Question
I'm attempting to use the new JSON column functionality for storing translations in a JSON column, as opposed to storing the in a separate table. My first attempt was to store translations in a
Dictionary<byte, string>
where the byte would be the language ID and a string the value, but that currently doesn't work, as described in #30707.So I have the following class that is being mapped to a JSON column.
When I use the
GetValueOrDefault
method in a query, the entire JSON column is parsed and the method is called in memory.This query:
Produces the following SQL:
Whereas if I grab the CZ property directly, like so:
That produces:
Is there a way to translate my
GetValueOrDefault
method to SQL so it would also grab the property directly in SQL usingJSONVALUE
?Also on a side note, I thought that whenever you use a projection to a non-tracked object in a query, the query is automatically a non-tracking once, but I'm getting the following exception when I omit the
AsNoTracking()
call on those example queries:Repro
Here's the full code to repro (requires a connection string to a running SQL server instance):
Provider and version information
EF Core version: 8.0.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 8.0
Operating system: Windows 10 22H2
IDE: Visual Studio 2022 17.8.1
The text was updated successfully, but these errors were encountered: