Mudanças significativas no EF Core 9 (EF9)
Esta página documenta as alterações de API e comportamento que têm o potencial de interromper a atualização de aplicativos existentes do EF Core 8 para o EF Core 9. Certifique-se de revisar as alterações importantes anteriores ao atualizar de uma versão anterior do EF Core.
- Mudanças significativas no EF Core 8
- Mudanças significativas no EF Core 7
- Mudanças significativas no EF Core 6
Estrutura de Destino
O EF Core 9 tem como alvo o .NET 8. Isso significa que os aplicativos existentes destinados ao .NET 8 podem continuar a fazê-lo. Os aplicativos destinados a versões mais antigas do .NET, .NET Core e .NET Framework precisarão direcionar o .NET 8 ou o .NET 9 para usar o EF Core 9.
Resumo
Observação
Se estiver a utilizar o Azure Cosmos DB, consulte a secção abaixo sobre alterações significativas no Azure Cosmos DB.
Alterações de alto impacto
É lançada uma exceção ao aplicar migrações se existirem mudanças no modelo pendentes
Problema de rastreamento #33732
Comportamento antigo
Se o modelo tiver alterações pendentes em comparação com a última migração, elas não serão aplicadas com o restante das migrações quando Migrate
for chamada.
Novo comportamento
A partir do EF Core 9.0, se o modelo tiver alterações pendentes em comparação com a última migração, será lançada uma exceção quando dotnet ef database update
, Migrate
ou MigrateAsync
forem chamados:
O modelo de contexto 'DbContext' tem alterações pendentes. Adicione uma nova migração antes de atualizar o banco de dados. Essa exceção pode ser suprimida ou registrada passando a ID do evento 'RelationalEventId.PendingModelChangesWarning' para o método 'ConfigureWarnings' em 'DbContext.OnConfiguring' ou 'AddDbContext'.
Porquê
Esquecer de adicionar uma nova migração depois de fazer alterações no modelo é um erro comum que pode ser difícil de diagnosticar em alguns casos. A nova exceção garante que o modelo do aplicativo corresponda ao banco de dados após a aplicação das migrações.
Atenuações
Existem várias situações comuns em que esta exceção pode ser lançada:
- Não há migrações. Isso é comum quando o banco de dados é atualizado por outros meios.
-
de mitigação: se você não planeja usar migrações para gerenciar o esquema de banco de dados, remova a chamada
Migrate
ouMigrateAsync
, caso contrário, adicione uma migração.
-
de mitigação: se você não planeja usar migrações para gerenciar o esquema de banco de dados, remova a chamada
- Há pelo menos uma migração, mas a captura do modelo está em falta. Isso é comum para migrações criadas manualmente.
- de mitigação: adicione uma nova migração usando ferramentas do EF, isso atualizará a captura de modelo.
- O modelo não foi modificado pelo desenvolvedor, mas é construído de forma não determinística, fazendo com que o EF o detete como modificado. Isso é comum quando
new DateTime()
,DateTime.Now
,DateTime.UtcNow
ouGuid.NewGuid()
são usados em objetos fornecidos aHasData()
.-
Mitigação: Adicione uma nova migração, examine seu conteúdo para localizar a causa e substitua os dados dinâmicos por um valor estático e codificado no modelo. A migração deve ser recriada após a correção do modelo. Se os dados dinâmicos tiverem que ser usados para semeadura, considere usar o novo padrão de semeadura em vez de
HasData()
.
-
Mitigação: Adicione uma nova migração, examine seu conteúdo para localizar a causa e substitua os dados dinâmicos por um valor estático e codificado no modelo. A migração deve ser recriada após a correção do modelo. Se os dados dinâmicos tiverem que ser usados para semeadura, considere usar o novo padrão de semeadura em vez de
- A última migração foi criada para um provedor diferente daquele usado para aplicar as migrações.
- Mitigação: Este é um cenário não suportado. O aviso pode ser suprimido usando o trecho de código abaixo, mas esse cenário provavelmente deixará de funcionar em uma versão futura do EF Core. A solução recomendada é para gerar um conjunto separado de migrações para cada provedor.
- As migrações são geradas ou escolhidas dinamicamente substituindo alguns dos serviços EF.
Mitigação: O aviso é um falso positivo neste caso e deve ser suprimido:
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning))
Se o seu cenário não se enquadrar em nenhum dos casos mencionados acima e adicionar uma nova migração resultar na criação da mesma migração cada vez ou numa migração vazia, e a exceção ainda for lançada, então crie um pequeno projeto de reprodução e partilhá-lo com a equipa do EF num novo assunto.
Uma exceção é lançada ao aplicar migrações numa transação explícita.
Comportamento antigo
Para aplicar migrações de forma resiliente, o seguinte padrão foi comumente usado:
await dbContext.Database.CreateExecutionStrategy().ExecuteAsync(async () =>
{
await using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken);
await dbContext.Database.MigrateAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
});
Novo comportamento
A partir do EF Core 9.0, as chamadas Migrate
e MigrateAsync
iniciarão uma transação e executarão os comandos usando um ExecutionStrategy
e, se seu aplicativo usar o padrão acima, uma exceção será lançada:
Foi gerado um erro para o aviso 'Microsoft.EntityFrameworkCore.Migrations.MigrationsUserTransactionWarning': uma transação foi iniciada antes de aplicar as migrações. Isso impede que um bloqueio de banco de dados seja adquirido e, portanto, o banco de dados não será protegido contra aplicativos de migração simultânea. As transações e a estratégia de execução já são gerenciadas pela EF conforme necessário. Remova a transação externa. Essa exceção pode ser suprimida ou registrada passando a ID do evento 'RelationalEventId.MigrationsUserTransactionWarning' para o método 'ConfigureWarnings' em 'DbContext.OnConfiguring' ou 'AddDbContext'.
Porquê
O uso de uma transação explícita impede que um bloqueio de banco de dados seja adquirido e, portanto, o banco de dados não será protegido contra aplicativos de migração simultânea, também limita o EF sobre como ele pode gerenciar as transações internamente.
Atenuações
Se houver apenas uma chamada de banco de dados dentro da transação, remova a transação externa e ExecutionStrategy
:
await dbContext.Database.MigrateAsync(cancellationToken);
Caso contrário, se o seu cenário exigir uma transação explícita e você tiver outro mecanismo em vigor para impedir o aplicativo de migração simultânea, ignore o aviso:
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsUserTransactionWarning))
Alterações de impacto médio
Microsoft.EntityFrameworkCore.Design
não encontrado ao usar ferramentas EF
Comportamento antigo
Anteriormente, as ferramentas EF exigiam que Microsoft.EntityFrameworkCore.Design
fossem referenciadas da seguinte maneira.
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="*.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Novo comportamento
A partir do .NET SDK 9.0.200, uma exceção é lançada quando uma ferramenta EF é invocada:
Não foi possível carregar o arquivo ou assembly 'Microsoft.EntityFrameworkCore.Design, Culture=neutral, PublicKeyToken=null'. O sistema não consegue encontrar o ficheiro especificado.
Porquê
As ferramentas EF dependiam de um comportamento não documentado do SDK do .NET que fazia com que ativos privados fossem incluídos no arquivo de .deps.json
gerado. Isso foi corrigido em sdk#45259. Infelizmente, a alteração do EF para levar isso em consideração não atende ao critério de manutenção do EF 9.0.x, portanto, será resolvido no EF 10.
Atenuações
Como solução alternativa antes do lançamento do EF 10, você pode marcar a referência de assembly Design
como publicável:
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<Publish>true</Publish>
</PackageReference>
Isso o incluirá no arquivo de .deps.json
gerado, mas tem um efeito colateral de copiar Microsoft.EntityFrameworkCore.Design.dll
para as pastas de saída e publicação.
Alterações de baixo impacto
EF.Functions.Unhex()
agora retorna byte[]?
Comportamento antigo
A função EF.Functions.Unhex()
foi previamente anotada para retornar byte[]
.
Novo comportamento
A partir do EF Core 9.0, o Unhex() agora é anotado para retornar byte[]?
.
Porquê
Unhex()
é traduzido para a função SQLite unhex
, que retorna NULL para entradas inválidas. Como resultado, Unhex()
devolveu null
para esses casos, violando a anotação.
Atenuações
Se você tiver certeza de que o conteúdo de texto passado para Unhex()
representa uma cadeia de caracteres hexadecimal válida, você pode simplesmente adicionar o operador de perdão nulo como uma asserção de que a invocação nunca retornará null:
var binaryData = await context.Blogs.Select(b => EF.Functions.Unhex(b.HexString)!).ToListAsync();
Caso contrário, adicione verificações de tempo de execução para "null" no valor de retorno de Unhex().
Aridade dos argumentos de anulabilidade da SqlFunctionExpression validada
Problema de Acompanhamento #33852
Comportamento antigo
Anteriormente, era possível criar um SqlFunctionExpression
com um número diferente de argumentos e argumentos de propagação de anulabilidade.
Novo comportamento
Começando com o EF Core 9.0, o EF agora lança se o número de argumentos e os argumentos de propagação de anulabilidade não corresponderem.
Porquê
Não ter um número correspondente de argumentos e argumentos de propagação de anulabilidade pode levar a um comportamento inesperado.
Atenuações
Certifique-se de que o argumentsPropagateNullability
tem o mesmo número de elementos que o arguments
. Em caso de dúvida, use false
para o argumento de anulabilidade.
O método ToString()
agora retorna uma string vazia para instâncias null
Comportamento antigo
Anteriormente, o EF retornava resultados inconsistentes para o método ToString()
quando o valor do argumento era null
. Por exemplo, ToString()
na propriedade bool?
com o valor null
que retornou null
, mas para expressões de não-propriedade bool?
cujo valor foi null
, retornou True
. O comportamento também foi inconsistente para outros tipos de dados, por exemplo, ToString()
em null
valor enum retornou string vazia.
Novo comportamento
A partir do EF Core 9.0, o método ToString()
agora retorna consistentemente a cadeia de caracteres vazia em todos os casos em que o valor do argumento é null
.
Porquê
O comportamento antigo era inconsistente em diferentes tipos de dados e situações, além de não estar alinhado com o comportamento de C#.
Atenuações
Para reverter para o comportamento antigo, reescreva a consulta de acordo:
var newBehavior = context.Entity.Select(x => x.NullableBool.ToString());
var oldBehavior = context.Entity.Select(x => x.NullableBool == null ? null : x.NullableBool.ToString());
As dependências da estrutura compartilhada foram atualizadas para 9.0.x
Comportamento antigo
As aplicações que usam o SDK do Microsoft.NET.Sdk.Web
e estão dirigidas a net8.0 resolveriam pacotes como os System.Text.Json
, Microsoft.Extensions.Caching.Memory
, Microsoft.Extensions.Configuration.Abstractions
, Microsoft.Extensions.Logging
e Microsoft.Extensions.DependencyModel
da estrutura compartilhada, portanto, essas assemblagens normalmente não seriam implantadas com a aplicação.
Novo comportamento
Embora o EF Core 9.0 ainda suporte net8.0, ele agora faz referência às versões 9.0.x do System.Text.Json
, Microsoft.Extensions.Caching.Memory
, Microsoft.Extensions.Configuration.Abstractions
, Microsoft.Extensions.Logging
e Microsoft.Extensions.DependencyModel
. As aplicações destinadas ao net8.0 não poderão utilizar a estrutura partilhada para evitar a implantação destes conjuntos.
Porquê
As versões de dependência correspondentes contêm as correções de segurança mais recentes e usá-las simplifica o modelo de manutenção para o EF Core.
Atenuações
Altere seu aplicativo para o destino net9.0 para obter o comportamento anterior.
Mudanças disruptivas do Azure Cosmos DB
Foi feito um trabalho extensivo para tornar o provedor do Azure Cosmos DB melhor na versão 9.0. As mudanças incluem uma série de alterações de impacto significativo; Se estiver a atualizar uma aplicação existente, leia cuidadosamente o que se segue.
Alterações de alto impacto
A propriedade discriminator agora chama-se $type
em vez de Discriminator
Comportamento antigo
O EF adiciona automaticamente uma propriedade discriminadora aos documentos JSON para identificar o tipo de entidade que o documento representa. Em versões anteriores do EF, essa propriedade JSON costumava ser nomeada Discriminator
por padrão.
Novo comportamento
A partir do EF Core 9.0, a propriedade discriminator agora é chamada de $type
por padrão. Se você tiver documentos existentes no Azure Cosmos DB de versões anteriores do EF, eles usarão a nomenclatura Discriminator
antiga e, após a atualização para o EF 9.0, as consultas nesses documentos falharão.
Porquê
Uma prática JSON emergente usa uma propriedade $type
em cenários onde o tipo de um documento precisa ser identificado. Por exemplo, o System.Text.Json do .NET também suporta polimorfismo, usando $type
como seu nome de propriedade discriminador padrão (docs). Para alinhar com o resto do ecossistema e facilitar a interoperação com ferramentas externas, o padrão foi alterado.
Atenuações
A atenuação mais fácil é simplesmente configurar o nome da propriedade discriminadora para ser Discriminator
, assim como antes:
modelBuilder.Entity<Session>().HasDiscriminator<string>("Discriminator");
Fazer isso para todos os tipos de entidade de nível superior fará com que o EF se comporte exatamente como antes.
Neste ponto, se desejar, você também pode atualizar todos os seus documentos para usar a nova nomenclatura $type
.
A propriedade id
agora contém apenas a propriedade de chave EF por predefinição
Comportamento antigo
Anteriormente, o EF inseria o valor discriminador do seu tipo de entidade na propriedade id
do documento. Por exemplo, se você salvou um tipo de entidade Blog
com uma propriedade Id
contendo 8, a propriedade JSON id
conterá Blog|8
.
Novo comportamento
A partir do EF Core 9.0, a propriedade JSON id
não contém mais o valor do discriminador e contém apenas o valor da propriedade da chave. Para o exemplo acima, a propriedade JSON id
seria simplesmente 8
. Se você tiver documentos existentes no Azure Cosmos DB de versões anteriores do EF, eles terão o valor discriminador na propriedade JSON id
e, após a atualização para o EF 9.0, as consultas nesses documentos falharão.
Porquê
Como a propriedade JSON id
deve ser exclusiva, o discriminador foi adicionado anteriormente a ela para permitir que entidades diferentes com o mesmo valor de chave existam. Por exemplo, isso permitia ter um Blog
e um Post
com uma propriedade Id
contendo o valor 8 dentro do mesmo contêiner e partição. Isso se alinhou melhor com os padrões de modelagem de dados de banco de dados relacional, onde cada tipo de entidade é mapeado para sua própria tabela e, portanto, tem seu próprio espaço-chave.
O EF 9.0 geralmente alterou o mapeamento para ficar mais alinhado com as práticas e expectativas comuns do Azure Cosmos DB NoSQL, em vez de corresponder às expectativas dos usuários provenientes de bancos de dados relacionais. Além disso, ter o valor discriminador na propriedade id
tornou mais difícil para ferramentas e sistemas externos interagirem com documentos JSON gerados pelo EF; esses sistemas externos geralmente não estão cientes dos valores do discriminador EF, que são, por padrão, derivados de tipos .NET.
Atenuações
A atenuação mais fácil é simplesmente configurar o EF para incluir o discriminador na propriedade JSON id
, como antes. Uma nova opção de configuração foi introduzida para este fim:
modelBuilder.Entity<Session>().HasDiscriminatorInJsonId();
Fazer isso para todos os tipos de entidade de nível superior fará com que o EF se comporte exatamente como antes.
Neste ponto, se desejar, você também pode atualizar todos os seus documentos para reescrever sua propriedade JSON id
. Observe que isso só é possível se entidades de tipos diferentes não compartilharem o mesmo valor de id dentro do mesmo contêiner.
A propriedade JSON id
é mapeada para a chave
Comportamento antigo
Anteriormente, o EF criava uma propriedade sombra mapeada para a propriedade JSON id
, a menos que uma das propriedades fosse mapeada explicitamente para id
.
Novo comportamento
A partir do EF Core 9, a propriedade chave será mapeada por convenção para a propriedade JSON id
, se possível. Isso significa que a propriedade de chave deixará de ser armazenada no documento sob um nome diferente, mantendo o mesmo valor, portanto, o código não-EF que utiliza os documentos e que depende dessa propriedade já não funcionaria corretamente.
Porquê
O EF 9.0 geralmente alterou o mapeamento para ficar mais alinhado com as práticas e expectativas comuns do Azure Cosmos DB NoSQL. E não é comum armazenar o valor da chave duas vezes no documento.
Atenuações
Se você quiser preservar o comportamento do EF Core 8, a atenuação mais fácil é usar uma nova opção de configuração que foi introduzida para essa finalidade:
modelBuilder.Entity<Session>().HasShadowId();
Fazer isso para todos os tipos de entidade de nível superior fará com que o EF se comporte exatamente como antes. Ou você pode aplicá-lo a todos os tipos de entidade no modelo com uma chamada:
modelBuilder.HasShadowIds();
Alterações de impacto médio
Não há mais suporte para a sincronização de E/S por meio do provedor do Azure Cosmos DB
Problema de rastreamento #32563
Comportamento antigo
Anteriormente, chamar métodos síncronos como ToList
ou SaveChanges
fazia com que o EF Core bloqueasse de forma síncrona usando .GetAwaiter().GetResult()
ao executar chamadas assíncronas no SDK do Azure Cosmos DB. Isso pode resultar em impasse.
Novo comportamento
A partir do EF Core 9.0, o EF agora lança por padrão ao tentar usar E/S síncronas. A mensagem de exceção é "O Azure Cosmos DB não oferece suporte a E/S síncrona. Certifique-se de usar e aguardar corretamente apenas métodos assíncronos ao usar o Entity Framework Core para acessar o Azure Cosmos DB. Consulte https://aka.ms/ef-cosmos-nosync para obter mais informações."
Porquê
O bloqueio síncrono em métodos assíncronos pode resultar em impasse, e o SDK do Azure Cosmos DB dá suporte apenas a métodos assíncronos.
Atenuações
No EF Core 9.0, o erro pode ser suprimido com:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.ConfigureWarnings(w => w.Ignore(CosmosEventId.SyncNotSupported));
}
Dito isso, os aplicativos devem parar de usar APIs de sincronização com o Azure Cosmos DB, pois isso não é suportado pelo SDK do Azure Cosmos DB. A capacidade de suprimir a exceção será removida em uma versão futura do EF Core, após a qual a única opção será usar APIs assíncronas.
As consultas SQL agora devem projetar valores JSON diretamente
Acompanhamento do Pedido #25527
Comportamento antigo
Anteriormente, o EF gerava consultas como as seguintes:
SELECT c["City"] FROM root c
Essas consultas fazem com que o Azure Cosmos DB envolva cada resultado em um objeto JSON, da seguinte maneira:
[
{
"City": "Berlin"
},
{
"City": "México D.F."
}
]
Novo comportamento
A partir do EF Core 9.0, o EF agora adiciona o modificador VALUE
às consultas da seguinte maneira:
SELECT VALUE c["City"] FROM root c
Essas consultas fazem com que o Azure Cosmos DB retorne os valores diretamente, sem ser encapsulado:
[
"Berlin",
"México D.F."
]
Se seu aplicativo fizer uso de consultas SQL, essas consultas provavelmente serão interrompidas após a atualização para o EF 9.0, pois não incluem o modificador VALUE
.
Porquê
Envolver cada resultado em um objeto JSON adicional pode causar degradação de desempenho em alguns cenários, incha a carga útil do resultado JSON e não é a maneira natural de trabalhar com o Azure Cosmos DB.
Atenuações
Para atenuar, basta adicionar o modificador VALUE
às projeções de suas consultas SQL, conforme mostrado acima.
Os resultados indefinidos agora são filtrados automaticamente dos resultados da consulta
Acompanhamento do Pedido #25527
Comportamento antigo
Anteriormente, o EF gerava consultas como as seguintes:
SELECT c["City"] FROM root c
Essas consultas fazem com que o Azure Cosmos DB envolva cada resultado em um objeto JSON, da seguinte maneira:
[
{
"City": "Berlin"
},
{
"City": "México D.F."
}
]
Se qualquer um dos resultados fosse indefinido (por exemplo, a propriedade City
estava ausente do documento), um documento vazio era retornado e o EF retornava null
para esse resultado.
Novo comportamento
A partir do EF Core 9.0, o EF agora adiciona o modificador VALUE
às consultas da seguinte maneira:
SELECT VALUE c["City"] FROM root c
Essas consultas fazem com que o Azure Cosmos DB retorne os valores diretamente, sem ser encapsulado:
[
"Berlin",
"México D.F."
]
O comportamento do Azure Cosmos DB é filtrar automaticamente undefined
valores dos resultados; Isso significa que, se uma das propriedades City
estiver ausente do documento, a consulta retornará apenas um único resultado, em vez de dois resultados, sendo um null
.
Porquê
Envolver cada resultado em um objeto JSON adicional pode causar degradação de desempenho em alguns cenários, incha a carga útil do resultado JSON e não é a maneira natural de trabalhar com o Azure Cosmos DB.
Atenuações
Se a obtenção de valores null
para resultados indefinidos for importante para seu aplicativo, agrupe os valores de undefined
para null
usando o novo operador EF.Functions.Coalesce
:
var users = await context.Customer
.Select(c => EF.Functions.CoalesceUndefined(c.City, null))
.ToListAsync();
As consultas traduzidas incorretamente não são mais traduzidas
Comportamento antigo
Anteriormente, o EF traduzia consultas como as seguintes:
var sessions = await context.Sessions
.Take(5)
.Where(s => s.Name.StartsWith("f"))
.ToListAsync();
No entanto, a tradução SQL para esta consulta estava incorreta:
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Session") AND STARTSWITH(c["Name"], "f"))
OFFSET 0 LIMIT @__p_0
Em SQL, a cláusula WHERE
é avaliada antes de as cláusulas OFFSET
e LIMIT
; mas na consulta LINQ acima, o operador Take
aparece antes do operador Where
. Como resultado, essas consultas podem retornar resultados incorretos.
Novo comportamento
A partir do EF Core 9.0, essas consultas não são mais traduzidas e uma exceção é lançada.
Porquê
Traduções incorretas podem causar corrupção silenciosa de dados, o que pode introduzir bugs difíceis de descobrir em seu aplicativo. O EF sempre prefere falhar rapidamente de forma proativa, agindo imediatamente, em vez de possivelmente causar corrupção de dados.
Atenuações
Se você estava satisfeito com o comportamento anterior e gostaria de executar o mesmo SQL, basta trocar a ordem dos operadores LINQ:
var sessions = await context.Sessions
.Where(s => s.Name.StartsWith("f"))
.Take(5)
.ToListAsync();
Infelizmente, o Azure Cosmos DB atualmente não oferece suporte às cláusulas OFFSET
e LIMIT
em subconsultas SQL, que é o que a tradução adequada da consulta LINQ original exige.
Alterações de baixo impacto
HasIndex
agora lança em vez de ser ignorado
Problema de rastreamento #34023
Comportamento antigo
Anteriormente, as chamadas para HasIndex eram ignoradas pelo provedor do EF Cosmos DB.
Novo comportamento
O provedor agora lança se HasIndex for especificado.
Porquê
No Azure Cosmos DB, todas as propriedades são indexadas por padrão e nenhuma indexação precisa ser especificada. Embora seja possível definir uma política de indexação personalizada, isso não é suportado atualmente pelo EF e pode ser feito por meio do Portal do Azure sem suporte ao EF. Como as chamadas HasIndex não estavam a fazer nada, deixaram de ser permitidas.
Atenuações
Remova todas as chamadas para HasIndex.
IncludeRootDiscriminatorInJsonId
foi renomeado para HasRootDiscriminatorInJsonId
após 9.0.0-rc.2
Problema de rastreamento #34717
Comportamento antigo
A API IncludeRootDiscriminatorInJsonId
foi introduzida na 9.0.0 rc.1.
Novo comportamento
Para a versão final do EF Core 9.0, a API foi renomeada para HasRootDiscriminatorInJsonId
Porquê
Outra API relacionada foi renomeada para começar com Has
em vez de Include
e, portanto, esta foi renomeada para consistência também.
Atenuações
Se o seu código estiver usando a API IncludeRootDiscriminatorInJsonId
, basta alterá-lo para fazer referência a HasRootDiscriminatorInJsonId
em vez disso.