Seguir
- Seguir:
- guia guia
- feed RSS
Obter ferramentas
Ferramentas .NETComo fazer
Khalid Abuhakmeh
Nesta postagem, veremos algumas armadilhas e ideias que usuários do EF Core como você podem querer considerar ao desenvolver um aplicativo.
Entity Framework Core (EF Core)é uma reescrita completa da estrutura de mapeamento de banco de dados de objetos da Microsoft. Começar a usar o EF Core é relativamente simples, mas dominá-lo pode levar uma carreira inteira.
Como usuário de longa data de versões anteriores do Entity Framework, comecei a escrever este post com muitas noções preconcebidas sobre as armadilhas dessa experiência. Embora algumas armadilhas conceituais tenham ocorrido em versões anteriores do EF, o cuidado da equipe do EF Core em lidar com problemas anteriores ficou evidente para mim quando li a documentação do EF Core e trabalhei nos exemplos de código desta postagem.
Sabendo que o EF Core é diferente, dediquei algum tempo para explorar a documentação do EF Core e determinar as armadilhas existentes que você pode encontrar ao iniciar sua jornada no EF Core. Compilei e consolidei essas informações para ajudá-lo a obter uma visão geral dos possíveis erros que você pode encontrar.
Embora este post esteja repleto de informações importantes, não é conclusivo.
Ferramentas globais x ferramentas locais
O EF Core passou por várias iterações para fornecer uma interface de linha de comando repetível. A atualização de versões anteriores pode nos levar a instalar as ferramentas EF Core CLI globalmente em nossos ambientes de desenvolvimento. Embora possamos instalar as ferramentas globalmente, é melhor criar versões das ferramentas da CLI e do EF Core juntas em sua solução.
Para instalar a ferramenta localmente para cada solução, primeiro precisamos criar um manifesto da ferramenta. Na pasta da solução, podemos executar o seguinteponto Net
comando.
novo manifesto de ferramenta dotnet
Este comando criará um novo.config
diretório com umdotnet-tools.json
arquivo. Podemos então instalar as ferramentas CLI em nossa solução localmente. A partir daqui, podemos instalar as ferramentas EF Core CLI.
ferramenta dotnet instalar dotnet-ef
A documentação do EF Corerecomenda que os desenvolvedores usem o pacote de ferramentas que corresponda à versão principal dos pacotes de tempo de execução. As últimas versões são5.0.1
para os pacotes CLI e EF Core, a partir da publicação do artigo. Instalar as ferramentas na solução nos ajuda a evitar desvios e conflitos ao trabalhar em várias soluções com versões variadas.
Adotando nomes não convencionais
Os pacotes de tempo de execução do EF Core 5 contêmconvenções em torno da nomenclatura do esquema, que normalmente são consideradas práticas recomendadas. O EF Core permite que os desenvolvedores trabalhem com unidades organizacionais para se adaptar a diferentes estilos de nomenclatura. Ainda assim, as modificações nas convenções de nomenclatura no EF Core vêm com custos de manutenção significativos e o potencial para introduzir bugs de mapeamento. Os desenvolvedores devem adotar os padrões do EF Core o máximo possível para evitar exceções e casos extremos estranhos.
Dependendo da sua organização e delegação de responsabilidade, pode ser melhor conversar sobre as convenções de nomenclatura do EF Core e adotá-las como uma metodologia compreendida para projetar e desenvolver o esquema. Os administradores e desenvolvedores de banco de dados devem trabalhar para agregar valor aos usuários. Se éimpossívelpara fazer isso por motivos organizacionais, considere a próxima seção como uma possível solução.
Esquecendo a engenharia reversa
Ao trabalhar com um banco de dados legado ou dinâmica de poder organizacional complicada, podemos ser tentados a criar cada entidade e definir cada relacionamento dentro doDbContext.OnModelCriando
método. Os desenvolvedores devem primeiro olhar paraoandaimesrecursos incorporados às ferramentas EF Core CLI.
Podemos pedir à CLI para estruturar entidades e relacionamentos de um banco de dados existente usando oandaime
comando.
dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook" Microsoft.EntityFrameworkCore.SqlServer
Devemos especificar o provedor de banco de dados apropriado durante o scaffolding para que o scaffolding possa respeitar a sintaxe SQL do nosso banco de dados.
Também podemos selecionar seletivamente partes de um banco de dados existente, especificando nomes de tabelas.
dotnet ef dbcontext scaffold ... --table Artista --table Álbum
As tabelas de direcionamento são úteis ao criar microsserviços ou aplicativos .NET projetados para executar uma tarefa de nicho.
Existem desvantagens no scaffolding que podemos evitar começando com uma abordagem Code-First. Podemos definir relacionamentos lógicos em C# que não podemos representar apenas por meio do esquema; esses conceitos incluem hierarquias de herança, tipos de propriedade e divisão de tabelas. Além disso, os mecanismos de simultaneidade não sofrem engenharia reversa peloandaime
comando. Por fim, os tipos de referência anuláveis também não sofrem engenharia reversa e devemos adicioná-los após o fato.
As maiores preocupações da engenharia reversa de um banco de dados existente vêm de mudanças de conceito que ocorrem a partir de uma base de código e esquema de banco de dados divergentes. Se o banco de dados for relativamente estável, isso pode não ser um problema. Ainda assim, um banco de dados em progresso ativo pode causar dores de cabeça aos desenvolvedores enquanto eles tentam acompanhar as mudanças de esquema.
Nem todos os bancos de dados são iguais
O EF Core fornece uma interface comum para vários mecanismos de banco de dados relacional. Esses provedores incluem SQLite, Microsoft SQL Server, PostgreSQL e Oracle. As semelhanças entre cada provedor podem nos levar a uma falsa sensação de segurança sobre a intercambialidade desses motores, mas é essencial reconhecer suas diferenças.
A abstração de consulta do EF Core é vazada, com muitos dos conceitos de banco de dados encontrando seu caminho para a interface. Os vazamentos conceituais não sãoruim, mas eles devem ser levados em consideração quando começamos a usar recursos comoDbFunction
eFromSql
para executar recursos específicos do mecanismo de banco de dados.
Ao testar, oA documentação do EF Core recomenda três opções:
- Executar testes no mesmo mecanismo de banco de dados usado na produção.
- Executar testes em algum outro mecanismo de banco de dados que é"mais fácil"gerenciar.
- Usando dublês de teste para evitar o uso de um banco de dados.
A melhor opção é executar nossos testes em um ambiente de produção, pois eliminaremos os problemas que podem surgir das variações do mecanismo. Pode ser difícil dependendo do banco de dados, mas com tecnologias de conteinerização comoDocker, o problema de gerenciar instâncias isoladas nunca foi tão fácil para os desenvolvedores.
Algumas pessoas podem querer testar em um mecanismo diferente, por exemplo, o SQL Server pode ser o mecanismo de banco de dados de destino, mas os testes são executados em uma instância do SQLite. Embora possível, essa abordagem leva a mais problemas, como diferenças de sintaxe SQL e a necessidade de gerenciar uma estratégia de migração totalmente diferente.
Finalmente, stubs ou mocks podem parecer uma"bom"ideia, mas os mecanismos de banco de dados são preenchidos com um grau de nuance e complexidade que é difícil de entender completamente sem um investimento de tempo significativo. A incompatibilidade entre o comportamento assumido do mecanismo e o comportamento real pode nos levar a introduzir bugs.
Consultas que não incluem dados relacionados
O EF Core abandonou o carregamento lento como um recurso padrão. As propriedades de navegação ainda existem como parte da abordagem de design Code-First, mas muitas dessas propriedades de navegação exigem explicitamente que o EF Core carregue os dados.
Dado o seguinteEntretenimentoDbContext
, nós temos umaFilme
modelo.
public abstract class Production{ public int Id { get; definir; } string pública Nome { get; definir; } Public DateTime Release { get; definir; } public List Caracteres { get; definir; } = new List(); public List Classificações { get; definir; } = new List();}public class Movie : Production{ public int DurationInMinutes { get; definir; } public double WorldwideBoxOfficeGross { get; definir; }}
EF Core não carregará oPersonagens
eavaliações
propriedades de navegação na consulta a seguir.
var filmes = banco de dados.Movies .OrderByDescending(x => x.WorldwideBoxOfficeGross);
Só depois de usar oIncluir
veremos as coleções preenchidas.
var filmes = banco de dados .Movies .Include(m => m.Characters) .Include(m => m.Ratings) .OrderByDescending(x => x.WorldwideBoxOfficeGross);
Esquecer de incluir dados importantes pode levar ao pânico quando os usuários pensam que o sistema não está salvando dados ou excluiu dados existentes.
Acompanhamento de consultas somente leitura
EF Core implementa oUnidade de trabalhopadrão, acompanhando as alterações em nossas entidades e, por fim, enviando essas alterações de volta ao nosso mecanismo de banco de dados. A abordagem tem muitas vantagens ao modificar dados, mas vem com um custo de desempenho perceptível.
Instanciando umDbContext
A instância é uma operação relativamente barata, em que a maior parte do custo de uso do EF Core vem da análise de expressão, operações de rede e rastreamento de objetos. Podemos desativar o rastreamento de objetos usando oAsNoTracking
método em nossas consultas LINQ.
var filmes = banco de dados .Movies .AsNoTracking() .OrderByDescending(x => x.WorldwideBoxOfficeGross);
Desativar o rastreamento de objetos pode acelerar cenários de leitura, como pontos de extremidade somente leitura em uma API HTTP. Existe um risco potencial de usar oAsNoTracking
recurso. Embora reduza o custo de processamento de entidades para rastreamento de objetos, pode aumentar a sobrecarga de memória. Vejamos um exemplo.
var filmes = banco de dados .Movies .AsNoTracking() .Include(m => m.Characters) .ThenInclude(c => c.Actor) .AsNoTracking() .OrderByDescending(x => x.WorldwideBoxOfficeGross);
No caso desta consulta, umAtor
pode estar em vários filmes. Como o EF Core não está mais rastreando entidades, o EF Core alocará uma entidade para o mesmoAtor
várias vezes.
Podemos optar pela resolução de identidade enquanto desativamos o rastreamento de objetos usando o recém-adicionadoAsNoTrackingWithIdentityResolution
método.
var filmes = banco de dados .Movies .AsNoTrackingWithIdentityResolution() .Include(m => m.Characters) .ThenInclude(c => c.Actor) .AsNoTracking() .OrderByDescending(x => x.WorldwideBoxOfficeGross);
Todas as instâncias do mesmoAtor
model apontará para o mesmo objeto, evitando assim a superalocação.
Não habilite o carregamento lento
Carregamento lentoé um recurso que tem causado inúmeros problemas de produção, e a equipe do EF Corelegitimamentetornou inconveniente habilitar esse recurso.
É altamente recomendávelnão habilitaresse recurso, pois as propriedades de navegação tornam-se mecanismos opacos que acionam idas e vindas desnecessárias e caras ao banco de dados.
Para habilitar o carregamento lento, as pessoas precisam instalar oMicrosoft.EntityFrameworkCore.Proxies
pacote.
dotnet adicionar pacote Microsoft.EntityFrameworkCore.Proxies
Em seguida, a partir doAo configurar
método de umDbContext
, podemos chamar oUseLazyLoadingProxies
método.
substituição protegida void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder .UseLazyLoadingProxies() .UseSqlServer(myConnectionString);
Vejamos um exemplo N+1 com nossoFilme
modelo.
var filmes = banco de dados .Movies .OrderByDescending(x => x.WorldwideBoxOfficeGross);foreach (var filme em filmes){ // uma chamada de banco de dados por Character foreach (var character in movie.Characters) { // chamada de banco de dados para Actor Console. WriteLine(personagem.Ator.Nome); }}
Embora possa parecer que executamos uma única consulta, conforme percorremos nossoFilme
entidade, estamos fazendo uma consulta adicional para cada propriedade de navegação. Para cadaFilme
(N), estamos fazendo uma chamada separada para o banco de dados para cadaPersonagem
entidade (+1). E neste exemplo, outra chamada separada paraAtor
. Isso é altamente ineficiente!Os amigos não permitem que os amigos ativem o carregamento lento.
Esquecer as projeções
Por mais que a abstração do EF Core pareça C#, é melhor tratá-la mais como a interface do banco de dados. Os modelos definidos em nossoDbContext
representam nosso esquema e devem ser usados para escrever consultas mais eficientes. Usar as entidades é equivalente a realizar umSelecione * Da Tabela
consulta. Não é erradoselecione *
, mas ao empregarSelecione
método, podemos usarprojeções, o que nos permite:
- Reduza a quantidade de dados transmitidos pela rede.
- Melhore os tempos de execução do SQL.
- Retorne explicitamente apenas os dados de que precisamos.
Vejamos como projetar nossoFilme
modelo em um resultado que inclui dados de personagens e atores.
var filmes = banco de dados .Movies .AsNoTracking() .OrderByDescending(x => x.WorldwideBoxOfficeGross) .Select(m => new { m.Name, Characters = m.Characters.Select(c => new { c.Name, Actor = c.Actor.Name }) });
Em vez de usar resultados de objetos anônimos, também podemos projetar diretamente em objetos de transferência de dados destinados a serem consumidos pelos chamadores. Neste exemplo, selecionamos diretamente em nossos modelos de resposta da API HTTP para máxima eficiência.
var filmes = banco de dados .Movies .AsNoTracking() .OrderByDescending(x => x.WorldwideBoxOfficeGross) .Select(m => new MovieResponse { Id = m.Id, Name = m.Name, Characters = m.Characters.Select(c => new CharacterResponse { Name = c.Name, Actor = c.Actor.Name }) });
Esquecer de adicionar índices
É fácil esquecer a escala dos dados com os quais lidaremos na produção durante o desenvolvimento. Além disso, à medida que nosso aplicativo cresce e adicionamos recursos, nossas necessidades de consulta mudam. A maioria dos mecanismos de banco de dados adicionará índices a chaves primárias e estrangeiras, mas também podemos ter colunas que fornecem outras oportunidades de particionamento.
Com Núcleo EF,podemos aplicar um índiceusando oModelBuilder
instância dentro doOnModelCreating
método. No momento em que escrevo este post, os índicessó pode ser aplicado com oModelBuilder
, e não há atributo de anotação de dados equivalente.
modelBuilder.Entity() .HasIndex(b => b.Release);
O EF Core tem muitas opções para especificar um índice, desde exclusividade, nomenclatura, filtragem, várias colunas e filtros aplicados.
Os índices são uma parte essencial da otimização do acesso ao banco de dados. É vital medir o desempenho da consulta e aplicar índices quando necessário.
Executando operações de migração
O EF Core oferece suporte a um modelo de migração muito aprimoradoem comparação com seu antecessor, o EF 6. O EF Core mais recente apresenta arquivos de migração amigáveis ao controle de versão, ferramentas CLI e fluxos de trabalho repetíveis.
Podemos querer permitir que nossos aplicativos executem migrações na inicialização do aplicativo, mas é melhor não fazer isso por vários motivos:
- Operações caras podem exceder o limite de tempo limite do SQL padrão do .NET, lançar exceções e deixar os aplicativos em um estado de inicialização interrompido.
- Várias instâncias de seu aplicativo podem tentar competir para aplicar migrações, causando debates e contenção desnecessária.
- As migrações são executadas sem mecanismos de verificação de qualidade e sem oportunidade de revisão.
Núcleo EFpode gerar scriptsque podemos aplicar a um banco de dados de produção. OA documentação da Microsoft sugereScripts SQL como a abordagem recomendada para implantar alterações de esquema em ambientes de produção:
- As equipes podem revisar os scripts SQL quanto à precisão e testar possíveis perdas de dados.
- Os scripts SQL podem ser usados em conjunto com uma tecnologia de implantação e integrados a um processo de integração contínua.
- Os scripts SQL podem ser fornecidos a uma unidade de administração de banco de dados e aplicados fora dos horários de pico.
Podemos usar as mesmas ferramentas EF CLI para gerar scripts SQL. A abordagem mais poderosa é usandoDe
ePara
argumentos.
script de migrações dotnet ef [de] [para]
Podemos deixar de fora oPara
argumento, pois podemos sugerir que queremos gerar até a migração mais recente.
Devemos sempre abordar a migração de dados de produção com extremo cuidado, pois qualquer modificação pode levar à perda de dados. Automatizar a aplicação de alterações de esquema é ideal, pois remove o potencial de erro humano.
Usando tabela por tipo
O EF Core tem dois modelos de herança:Tabela por hierarquia (TPH)eTabela por tipo (TPT).
A abordagem TPH usa uma única tabela com colunas para cada propriedade exclusiva de uma entidade com umDiscriminador
coluna. No exemplo a seguir, ambosFilme
eSeries
compartilhar umProduções
mesa.
public abstract class Production{ public int Id { get; definir; } string pública Nome { get; definir; } Public DateTime Release { get; definir; } public List Caracteres { get; definir; } = new List(); public List Classificações { get; definir; } = new List();}public class Movie : Production{ public int DurationInMinutes { get; definir; } public double WorldwideBoxOfficeGross { get; definir; }}public class Series : Production{ public int NumberOfEpisodes { get; definir; }}
Filme
as linhas irão conterNulo
valores para oNumberOfEpisodes
colunas, enquantoSeries
linhas terão vazioDuraçãoEmMinutos
eWorldwideBoxOfficeGross
colunas.
A abordagem TPT colocaria cada entidade respectiva em uma tabela separada.
As propriedades que pertencem exclusivamente a um tipo base ou tipo derivado são armazenadas em uma tabela que mapeia para esse tipo. As tabelas que mapeiam para tipos derivados também armazenam uma chave estrangeira que une a tabela derivada à tabela base. —Documentação da Microsoft
(Video) The Howling Mines | Critical Role: THE MIGHTY NEIN | Episode 6
Embora possa parecer uma abordagem "mais limpa" para a modelagem de dados, ela tem um custo caro ao fazer consultas em toda a hierarquia.
Vejamos uma consulta direta.
var mais altaRated = database .Productions .Select(x => new { id = x.Id, name = x.Name, avg = x.Ratings.Average(r => r.Stars), type = x.GetType(). Nome }) .OrderByDescending(x => x.avg);
Com o TPH, geraríamos uma instrução SQL equivalente à consulta de uma única tabela.
selecione * de [Produções]
Com o TPT, agora precisaríamos juntar várias tabelas. O custo de unir várias tabelas aumenta à medida que adicionamos novas entidades à nossa hierarquia, até o ponto em que o desempenho de nosso aplicativo é prejudicado e temos alguns usuários infelizes.
Os desenvolvedores só devem considerar o uso de uma abordagem TPT quando não houver chance de precisar executar uma consulta hierárquica que envolva várias entidades. Mesmo nesse cenário, porém, o que a herança de entidade está alcançando?
Duplicação de colunas compartilhadas
Ao usar herança, geralmente definimos propriedades compartilhadas em tipos básicos, mas pode haver uma instância em que esse não seja o caso. Vejamos um exemplo em que dois modelos em nossa hierarquia compartilham o mesmo nome de propriedade sem herdar do tipo base.
classe abstrata pública Veículo {}classe pública Motocicleta : Veículo {}classe pública Carro : Veículo{ public int NumberOfDoors { get; definir; }}public class Plane : Vehicle{ public int NumberOfDoors { get; definir; }}
Se não for explicitamente instruído a usar a mesma coluna, o EF Core criará uma coluna duplicada paraNumberOfDoors
. UsandoModelBuilder
, podemos usar a mesma coluna.
modelBuilder.Entity() .Property(c => c.NumberOfDoors) .HasColumnName(nameof(Car.NumberOfDoors));modelBuilder.Entity() .Property(c => c.NumberOfDoors) .HasColumnName( nameof(Plane.NumberOfDoors));
O uso da interface do construtor de modelo para combinar colunas deve aumentar a eficiência das consultas SQL.
Excluindo dados
"Excluir" é uma daquelas palavras que podem ter um significado diferente dependendo da nossa perspectiva. Como usuários, queremos exclusões para contabilizar erros e recuperar qualquer informação que removemos acidentalmente. Como desenvolvedores, e no caso do EF Core, excluir é inabalável e sem remorso sobre a remoção permanente de nossos dados. Ao desenvolver um novo aplicativo, podemos tender para a conveniência de exclusões definitivas, mas podemos adicionarexclusões suavesaos nossos aplicativos com um pouco de esforço.
O EF Core vem comFiltros de consulta globaisque fazem a implementaçãoexclusões suavesdireto. Primeiro começamos adicionando uma coluna booleana deEsta deletado
à nossa entidade. Quando esta coluna éverdadeiro
, então nossos dados são excluídos de forma reversível.
public abstract class Production{ public int Id { get; definir; } string pública Nome { get; definir; } Public DateTime Release { get; definir; } public bool IsDeleted { get; definir; } public List Caracteres { get; definir; } = new List(); public List Classificações { get; definir; } = new List();}
Na nossaOnModelCreating
método, podemos aplicar um filtro de consulta que se aplica a qualquer consulta realizada noProdução
entidade.
modelBuilder.Entity() .HasQueryFilter(m => !m.IsDeleted);
Podemos escrever consultas como normalmente faríamos com nosso filtro de consulta aplicado a qualquerProdução
consulta.
explosão cartesiana
As junções são parte integrante dos bancos de dados relacionais. Eles nos permitem criar linhas de tabelas relacionadas. Embora seja um recurso poderoso, ele vem com desvantagens. Tome a seguinte relação.
Filme -> Personagens -> Ator
Um filme em que um ator interpreta vários personagens duplicará os dados doFilme
eAtor
tabelas em nossos resultados. Vamos escrever uma consulta e ver o SQL gerado. Dada a seguinte instrução LINQ:
SELECT "p".."Id", "p".."Discriminador", "p".."Nome", "p".."Release", "p".."DuraçãoEmMinutos", "p".."WorldwideBoxOfficeGross", " t"."Id", "t".."ActorId", "t".."Name", "t".."ProductionId", "t"."Id0", "t"."Name0"FROM "Productions" AS "p"LEFT JOIN ( SELECT "c".."Id", "c".."ActorId", "c".."Nome", "c".."ProductionId", "a"."Id" AS "Id0 ", "a".."Nome" AS "Nome0" FROM "Personagens" AS "c" INNER JOIN "Atores" AS "a" ON "c"."ActorId" = "a"."Id") AS "t " ON "p".."Id" = "t".."ProductionId"WHERE "p".."Discriminador" = 'Filme'ORDER BY "p".."WorldwideBoxOfficeGross" DESC, "p".."Id", "t "."Id", "t".."Id0"
Executando nossa consulta em um banco de dados, veremos estes resultados:
1,Filme,Avengers: Endgame,2019-04-26 00:00:00,181,2797800564.0,1,1,Tony Stark,1,1,Robert Downey Jr.1,Filme,Avengers: Endgame,2019-04-26 00 :00:00,181,2797800564.0,2,2,Steve Rogers,1,2,Chris Evans1,Filme,Avengers: Endgame,2019-04-26 00:00:00,181,2797800564.0,3,3,Okoye,1,3, Danai Guira5,Filme,Downton Abbey,2020-09-20 00:00:00,120,194051302.0,8,8,Violet Crawley,5,8,Maggie Smith5,Filme,Downton Abbey,2020-09-20 00:00:00,120 ,194051302.0,9,9,Lady Mary Crawley,5,9,Michelle Dockery3,Filme,Ip Man 4,2019-12-25 00:00:00,105,192617891.0,6,6,Ip Man,3,6,Donny Yen4 ,Filme,Gemini Man,2019/11/20 00:00:00,116,166623705.0,7,7,Henry Brogan,4,7,Will Smith2,Filme,O Rei Leão,2019/07/19 00:00:00,118, 1654791102.0,4,4,Simba,2,4,Donald Glover2,Filme,O Rei Leão,2019-07-19 00:00:00,118,1654791102.0,5,5,Nala,2,5,Beyoncé
Como podemos ver, as informações do filme se repetem. Esses dados repetidos podem levar ao que é conhecido comoexplosão cartesianase houver tabelas suficientes envolvidas em uma consulta.
EF Core introduziu umAsSplitQuery
método que permite que o Entity Framework divida cada entidade relacionada em uma consulta em cada tabela.
var filmes = banco de dados .Movies .AsSplitQuery() .Include(m => m.Characters) .ThenInclude(c => c.Actor) .OrderByDescending(x => x.WorldwideBoxOfficeGross);
Ao adicionar oAsSplitQuery
método, agora temos três instruções SQL paraFilmes
,Personagens
, eAtor
. Observando a string de consulta de diagnóstico do EF Core, vemos o seguinte SQL.
SELECT "p".."Id", "p".."Discriminador", "p".."Nome", "p".."Release", "p".."DuraçãoEmMinutos", "p".."WorldwideBoxOfficeGross"FROM " Productions" AS "p"WHERE "p".."Discriminador" = 'Filme'ORDER BY "p".."WorldwideBoxOfficeGross" DESC, "p".."Id"
Esta consulta LINQ está sendo executada no modo de consulta dividida. O SQL mostrado é para a primeira consulta a ser executada. Consultas adicionais também podem ser executadas dependendo dos resultados da primeira consulta.
Vale a pena experimentarAsSplitQuery
, pois pode acelerar as consultas e reduzir o tráfego de rede ao remover a duplicação de dados.
Constantes em expressões
O EF Core otimiza as consultas armazenando em cache as expressões LINQ, mas primeiro ele precisa compilar nossas expressões LINQ. Esse processamento de expressões LINQ é perceptível em ambientes de produção. Veja o exemplo a seguir.
var first = database.Movies.First(m => m.Id == 1);var second = database.Movies.First(m => m.Id == 2);
Essas duas consultas parecem idênticas, mas são compiladas em duas entradas de cache separadas quando o identificador é uma constante. Podemos otimizar essas consultas para compartilhar a mesma forma com modificações aparentemente menores.
var id = 1;var first = database.Movies.First(m => m.Id == id);id = 2;var second = database.Movies.First(m => m.Id == id);
Agora obtemos os mesmos resultados e armazenamos em cache a mesma consulta em duas instâncias separadas de seu uso. Usando constantes em nossas consultas, podemos inadvertidamente poluir o cache de consulta interno do EF Core e prejudicar o desempenho geral da consulta.
Injeção de SQL por acidente
A interpolação de strings é um dos melhores recursos do C# da última década. É uma conveniência que economizou incontáveis horas de cada desenvolvedor C# embaralhando valores de índice em strings de formato. O EF Core permite o uso de interpolação de cadeia de caracteres ao usar SQL bruto. Ainda assim, os desenvolvedores devem ter cuidado para não refatorar seu código em um estado vulnerável à injeção de SQL inadvertidamente. Vamos começar com um SQL parametrizado usando uma string interpolada.
var id = 1;var results = database .Movies .FromSqlInterpolated($"Selecione * From Movies where id = {id}") .ToQueryString();
Quando olhamos para o SQL de nossa consulta, vemos que o EF Core parametrizou oeu ia
.
.param set p0 1SELECT "p".."Id", "p".."Discriminador", "p".."Nome", "p".."Release", "p".."DuraçãoEmMinutos", "p"." WorldwideBoxOfficeGross"FROM ( Select * From Movies where id = @p0) AS "p"WHERE "p"."Discriminator" = 'Movie'
Podemos querer mover nossa consulta para outra variável para umlimpadorprocurando instrução LINQ.
var id = 1;var query = $"Selecione * Dos filmes where id = {id}";var results = banco de dados .Movies .FromSqlRaw(query) .ToQueryString();
Vamos ver qual é a instrução SQL resultante após nossa refatoração.
SELECT "p".."Id", "p".."Discriminador", "p".."Nome", "p".."Release", "p".."DuraçãoEmMinutos", "p".."WorldwideBoxOfficeGross"FROM ( Selecione * From Movies where id = 1) AS "p"WHERE "p".."Discriminator" = 'Filme'
Caramba! Acabamos de introduzir uma possível injeção de SQL. O EF Core não está mais parametrizando nossoeu ia
variável. O risco se torna mais perigoso se aceitarmos a entrada do usuário na forma de um parâmetro de string.
A abstração do EF Core protege os desenvolvedores da introdução de ataques de injeção de SQL. Ainda assim, ao usar as interfaces SQL, os desenvolvedores correm um risco maior de perfurar a proteção fornecida pelo uso de instruções LINQ.
Atualizações Ineficientes
Dada a interface LINQ do EF Core, é tentador fazer todas as nossas operações usando nossas entidades C#. Ao lidar com grandes operações de conjunto de dados, é melhor adotar o mecanismo de armazenamento de dados subjacente em vez do LINQ em milhares de registros.
var filmes = banco de dados .Movies .OrderByDescending(x => x.WorldwideBoxOfficeGross);foreach (var filme em filmes){ filme.DurationInMinutes += 10; // trailers}database.SaveChanges();
Em vez disso, poderíamos usar uma única consulta SQL.
database.Database .ExecuteSqlRaw( "UPDATE [Productions] " + "SET [DurationInMinutes] = [DurationInMinutes] + 10 " + "WHERE Discriminator = 'Movie';");
Alcançamos o mesmo resultado sem o custo de conversas na rede.
Resiliência de conexão
Ao desenvolver em bancos de dados locais, às vezes podemos considerar a estabilidade de nossas conexões garantida. A produção é um pouco menos confiável quando se trata de confiabilidade de conexão.
O EF Core possui mecanismos de resiliência de conexão integrados que dão suporte a estratégias de repetição e resfriamento. Eles são ativados por padrão ao usar mecanismos de banco de dados variantes do SQL Server, mas podemos configurar a resiliência para nossas necessidades específicas.
substituição protegida void OnConfiguring(DbContextOptionsBuilder optionsBuilder){ optionsBuilder .UseSqlServer( "", options => options.EnableRetryOnFailure( maxRetryCount: 4, maxRetryDelay: TimeSpan.FromSeconds(1), errorNumbersToAdd: new int[] { } )) ;}
É importante entender que as conexões com bancos de dados não são garantidas como estáveis. Usando um software de monitoramento, notamos que há discrepâncias estranhas no desempenho, provavelmente devido à estratégia de execução que compensa uma falha na conexão ou o tempo limite do SQL. Às vezes, podemos corrigir esses problemas por meio do gerenciamento de infraestrutura ou otimizando as consultas para sobrecarregar menos nosso banco de dados.
Conclusão
O EF Core melhorou muitos problemas encontrados em versões anteriores do Entity Framework. Embora ainda seja uma abstração para mecanismos de banco de dados, as adições de interface ao EF Core parecem abraçar a inevitabilidade de lidar com o banco de dados.
Os aprimoramentos incluem combinar, dividir e executar SQL de maneiras anteriormente complicadas. O EF Core também oferece mais opções de extensibilidade aos desenvolvedores para lidar com problemas de acesso a dados, como filtragem de consultas, divisão de tabelas e herança. Os benefícios adicionais de uma melhor depuração no EF Core tornam a biblioteca mais fácil de recomendar aos desenvolvedores. O EF Core é menos uma caixa preta do que as versões anteriores, ajudando os desenvolvedores a diagnosticar problemas mais rapidamente.
Como palavra final, os novos aprimoramentos do EF Core abrangem o banco de dados e o SQL mais do que nunca, e é por isso que é importante aprendermos tudo o que pudermos sobre o banco de dados que escolhemos. Compreender o funcionamento interno de um mecanismo de banco de dados e a sintaxe SQL específica dará aos desenvolvedores a vantagem mais significativa, pois os desenvolvedores podem usar esse conhecimento para otimizar qualquer limitação do EF Core.
Obrigado por ler e, por favor, deixe quaisquer comentários e perguntas abaixo. _
.NET Core Estrutura de entidade ReSharper Cavaleiro
- Compartilhar
Post anterior Estudo de caso: como a carteira Wasabi é construída usando .NET, Avalonia e JetBrains Rider.NET anotado mensalmente | Março de 2021 Próxima postagem
Assine as atualizações do blog
Descubra mais
FAQs
What is Entity Framework Core 5? ›
Entity Framework (EF) Core is a lightweight, extensible, open source and cross-platform version of the popular Entity Framework data access technology. EF Core can serve as an object-relational mapper (O/RM), which: Enables .NET developers to work with a database using .NET objects.
What is difference between Entity Framework 5 and 6? ›EF5 is built into the core of . NET 4.5, whereas EF6 has been shifted out, and is open source. This means that you must add the new EF6 assemblies to all of the relevant projects in the solution, in particular the entry project. This means that you must remove assembly System.
Why you shouldn't use Entity Framework? ›The most common issue usually is on the programmer's side: firing the SQL execution on middle-query time, when it's not supposed to get the data yet and the query results being extensive (too many records) without the programmer even thinking about it.
What is required for Entity Framework 5? ›Prerequisites: Basic knowledge of . Net Framework, C#, Visual Studio and MS SQL Server is required. Audience: Basic tutorials are helpful for anyone who doesn't know anything about Entity Framework and would like to learn it from scratch.
Can I use Entity Framework with .NET 5? ›With the . NET 5 release comes the newest Entity Framework Core version, unsurprisingly called Entity Framework Core 5 (EF Core 5).
Is Entity Framework same as .NET core? ›Entity Framework Core is an object-database mapper (and a successor to Entity Framework). . NET Core is a cross-platform software framework developed by Microsoft (and a successor to . NET Framework).
When would you use EF6 vs EF Core? ›Keep using EF6 if the data access code is stable and not likely to evolve or need new features. Port to EF Core if the data access code is evolving or if the app needs new features only available in EF Core. Porting to EF Core is also often done for performance.
Which version of Entity Framework should I use? ›Entity Framework Core is the only actively developed version of Entity Framework and we recommend using it for all new code.
Which Entity Framework approach is better? ›As in this diagram, if we already have domain classes, the Code First approach is best suited for our application. The same as if we have a database, Database First is a good option. If we don't have model classes and a database and require a visual entity designer tool then Model First is best suited.
What is Entity Framework for dummies? ›Entity framework is an Object Relational Mapping (ORM) framework that offers an automated mechanism to developers for storing and accessing the data in the database. This tutorial covers the features of Entity Framework using Code First approach. It also explains the new features introduced in Entity Framework 6.
Which is better MVC or Entity Framework? ›
MVC is framework mainly concentrates on how you deliver a webpage from server to client. Entity framework is an object relational mapper which helps you to abstract different types of databases (MSSQL,MySQL etc) and helps querying objects instead of having sql strings in our project. Hope this helps!
How to migrate Entity Framework 5 to 6? ›- Uninstall Entity Framework 5 in Visual Studio Package Manager Console. ...
- Install Entity Framework 6 in Package Manager Console. ...
- Delete the following namespaces from your application: ...
- Add the following namespaces to your application:
EF Core 7.0 (EF7) was released in November 2022. You can run and debug into the samples by downloading the sample code from GitHub. Each section links to the source code specific to that section.
What database does Entity Framework use? ›Entity Framework is a modern object-relation mapper that lets you build a clean, portable, and high-level data access layer with .NET (C#) across a variety of databases, including SQL Database (on-premises and Azure), SQLite, MySQL, PostgreSQL, and Azure Cosmos DB.
What is the difference between .NET and Entity Framework? ›Some of the key differences between ADO.NET and the Entity Framework are as below: Performance: ADO.NET is much faster compared to the Entity Framework. Because ADO.NET always establishes the connection directly to the database. That's why it provides much better performance compared to the Entity Framework.
What is Entity Framework good for? ›The Entity Framework enables developers to work with data in the form of domain-specific objects and properties, such as customers and customer addresses, without having to concern themselves with the underlying database tables and columns where this data is stored.
Is .NET 5 backwards compatible with .NET Framework? ›The . NET Framework 4.5 and later versions are backward-compatible with apps that were built with earlier versions of the . NET Framework. In other words, apps and components built with previous versions will work without modification on the .
Why .NET Core is better than .NET Framework? ›NET Core is faster than . NET Framework because the architecture of . NET Core is written or restructured from scratch to make it a modular, lightweight, fast, and cross-platform Framework. The Applications require technologies like workflow, webforms or WCF that are not present in .
Is .NET Core in demand? ›High demand in the job market
NET developers are in high demand among startups and big tech companies alike. Employers are always seeking developers with expertise in . NET and C# since these technologies are now frequently used in enterprise-level applications.
There are three approaches to model your entities in Entity Framework: Code First, Model First, and Database First.
Does EF Core 5 require .NET 5? ›
Entity Framework Core 5.0
NET Standard 2.1. This means: EF Core 5.0 runs on . NET Core 3.1; it does not require .
Entity Framework Core is the new version of Entity Framework after EF 6.x. It is open-source, lightweight, extensible and a cross-platform version of Entity Framework data access technology. Entity Framework is an Object/Relational Mapping (O/RM) framework.
What is the difference between LINQ and EF core? ›LINQ allows you to use C# (or your . NET language of choice) to write strongly typed queries. It uses your derived context and entity classes to reference database objects. EF Core passes a representation of the LINQ query to the database provider.
Which is better LINQ or Entity Framework? ›First off, if you're starting a new project, use Entity Framework ("EF") instead of Linq to SQL because it now generates far better SQL (more like Linq to SQL does) and is easier to maintain ("L2S").
What are the two types of Entity Framework? ›There are two types of Entities in Entity Framework: POCO Entities and Dynamic Proxy Entities.
Is Entity Framework better than stored procedures? ›Stored procedures handle large quantities of data much better; in fact EF has some limitations on how much data can be handled.
Is EF core code first or database first? ›The entity framework will create the database with tables as per the entities classes defined in the application. So code is created first and this code is responsible to create the database using commands available in the EF Core tools package for the creation of the database.
Which one is best code first or database first? ›Code First is for green field projects and if you have an existing database you should use database first, again it's not right at all because you can reverse-engineer your existing database to create a Code First model and then use Code First Migrations for any subsequent changes afterwards.
What is the difference between enterprise library and Entity Framework? ›Entity Framework provides you more options as you can create a database from code classes and can be used if the application is looking for ORM. Enterprise Library is a more robust framework or class library written with performance and resource management best practices.
What are the two main concepts Entity Framework uses? ›Entity Framework approaches
At present, EF mainly allows two types of approaches related to this use. They are Database-First and Code-First (the first being absent from EF7, but still valid up to version 6.1.
Is Entity Framework Core slow? ›
Entity Framework is a great tool, but in some cases its performance is slow. One such case arises when complex queries use “Contains.”
What is advantage and disadvantage of Entity Framework? ›Easy to map business objects (with drag & drop tables on environment). It keeps a good performance when you work with a small / middle domain model. Disadvantages: You have to think in a non-traditional way of handling data , not available for every database.
What language does Entity Framework use? ›ADO.NET Entity Framework uses a variant of the Structured Query Language, named Entity SQL, which is aimed at writing declarative queries and updates over entities and entity relationships – at the conceptual level.
Why was Entity Framework created? ›It enables developers to work with data using objects of domain specific classes without focusing on the underlying database tables and columns where this data is stored.
Which .NET framework supports Entity Framework? ›EF Core is a . NET library. Both EF Core versions 6.0 and 7.0 target . NET version 6.0.
Is MVC outdated? ›ASP.NET MVC is not outdated per se. It's still a competent . NET framework. But we recommend avoiding it for new projects, as it is discontinued.
Why we use Web API instead of MVC? ›Asp.Net MVC is used to create web applications that return both views and data but Asp.Net Web API is used to create full-blown HTTP services with an easy and simple way that returns only data, not view. Web API helps to build REST-ful services over the .
Why API is better than MVC? ›The Web API returns the data in various formats, such as JSON, XML and other format based on the accept header of the request. But the MVC returns the data in the JSON format by using JSONResult. The Web API supports content negotiation, self hosting. All these are not supported by the MVC.
Should I use .NET 5 or 6? ›NET 6 are supported on multiple operating systems, including Windows, Linux, Android, iOS /tvOS, and macOS. The only difference is that . NET 6 is further supported on Windows Arms64 and macOS Apple Silicon while . NET 5 is not.
How do I seed data in .NET core? ›One way to seed data in EF Core is by using the DbContext. Database. EnsureCreated() method in your DbContext class. This method will create the database and apply any seed data that you have defined in your DbContext class.
How do I change my target framework to .NET Core 5? ›
- In Solution Explorer, open the right-click context menu for the project that you want to change, and then choose Properties.
- In the left column of the Properties window, choose the Application tab. ...
- In the Target Framework list, choose the version that you want.
Code first: EF Core allows developers to create a database from code, which enables a more agile and test-driven development workflow. LINQ support: EF Core supports LINQ, a powerful and expressive query language, which allows developers to write efficient and readable queries using C# or Visual Basic.
What is EF core for beginners? ›Entity Framework Core is a modern object-database mapper for . NET. It simplifies working with various databases (including Azure Cosmos DB, MySQL, PostgreSQL, SQL Server, and SQLite) using strongly-typed .
What are the three main types of entities database? ›- Intangible Entity: Intangible Entities are those entities which exist only logically and have no physical existence. ...
- Strong Entity Type: Strong entity are those entity types which has a key attribute. ...
- Weak Entity Type : Weak entity type doesn't have a key attribute.
EF Core 6.0 performance is now 70% faster on the industry-standard TechEmpower Fortunes benchmark, compared to 5.0. This is the full-stack perf improvement, including improvements in the benchmark code, the . NET runtime, etc.
What is the difference between dataset and Entity Framework? ›DataSets give you a basic in-memory database that you can query and fill from a data source such as a database. Queries against datasets are executed against in-memory data. Entity Framework gives you a translation layer that translates LINQ queries to your database's SQL dialect.
What's new in Entity Framework Core 5? ›EF Core 5.0 now allows a single LINQ query including related collections to be split into multiple SQL queries. This can significantly improve performance, but can result in inconsistency in the results returned if the data changes between the two queries.
What is Entity Framework used for? ›The Entity Framework enables developers to work with data in the form of domain-specific objects and properties, such as customers and customer addresses, without having to concern themselves with the underlying database tables and columns where this data is stored.
What is the core version of Entity Framework? ›Release | Target framework | Supported until |
---|---|---|
EF Core 7.0 | .NET 6 | May 14, 2024 |
EF Core 6.0 | .NET 6 | November 12, 2024 (LTS) |
EF Core 5.0 | .NET Standard 2.1 | Expired May 10, 2022 |
EF Core 3.1 | .NET Standard 2.0 | Expired December 13, 2022 |
Keep using EF6 if the data access code is stable and not likely to evolve or need new features. Port to EF Core if the data access code is evolving or if the app needs new features only available in EF Core. Porting to EF Core is also often done for performance.
Is Entity Framework still relevant? ›
Entity Framework 1 and 4 are considered legacy and should not be used. The first version of Entity Framework and Entity Framework 4 are fully contained in the . NET Framework.
How to upgrade Entity Framework Core 5 to 6? ›- Right-click on your project and select Manage NuGet Packages...
- Under the Online tab select EntityFramework and click Install. Note. If a previous version of the EntityFramework NuGet package was installed this will upgrade it to EF6.
- From the Visual Studio menu, select Project > Manage NuGet Packages.
- Click on the Browse or the Updates tab.
- To install or update the SQL Server provider, select the Microsoft. EntityFrameworkCore. SqlServer package, and confirm.
Entity Framework (EF) is an object-relational mapper for . NET developers that allows them to work with relational data using domain-specific objects. It eliminates the majority of the data-access code that developers must routinely write.
What are the benefits of Entity Framework? ›What are the advantages of the Entity Framework? Entity Framework helps to reduce development time and development cost. It provides auto-generated code and allows developers to visually design models and mapping of databases. It allows easy mapping of Business Objects.
What is the newest Entity Framework? ›Entity Framework Core 8, scheduled for release in November 2023, brings new features and improvements to features already introduced in EF Core 7. Notable features include support for raw SQL queries for unmapped types, lazy-loading improvements, and support for TimeOnly and DateOnly SQL Server data types.
Which .NET Framework supports Entity Framework? ›EF Core is a . NET library. Both EF Core versions 6.0 and 7.0 target . NET version 6.0.
What is better than Entity Framework? ›Dapper is generally faster than EF Core because it uses raw SQL queries and has less overhead. However, EF Core provides caching and other performance optimizations that can sometimes make it faster. Dapper is simpler than EF Core because it uses raw SQL queries and has fewer features.
What are the drawbacks of EF core? ›Lazy loading is the main drawbacks of EF. Its syntax is complicated. Its logical schema is not able to understand business entities and relation among each other. Logical schema of database is not capable of using certain parts of application.