Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Embora a consulta permita que você leia dados do banco de dados, salvar dados significa adicionar novas entidades ao banco de dados, remover entidades ou modificar as propriedades de entidades existentes de alguma forma. O EF Core (Entity Framework Core) dá suporte a duas abordagens fundamentais para salvar dados no banco de dados.
Abordagem 1: controle de alterações e SaveChanges
Em muitos cenários, seu programa precisa consultar alguns dados do banco de dados, executar alguma modificação nele e salvar essas modificações de volta; às vezes, isso é chamado de "unidade de trabalho". Por exemplo, vamos supor que você tenha um conjunto de Blogs e que gostaria de alterar a Url propriedade de um deles. No EF, isso normalmente é feito da seguinte maneira:
using (var context = new BloggingContext())
{
var blog = await context.Blogs.SingleAsync(b => b.Url == "http://example.com");
blog.Url = "http://example.com/blog";
await context.SaveChangesAsync();
}
O código acima executa as seguintes etapas:
- Ele usa uma consulta LINQ regular para carregar uma entidade do banco de dados (veja consultar dados). As consultas do EF estão configuradas para rastreamento por padrão, ou seja, o EF rastreia as entidades carregadas em seu rastreador de alterações interno.
- A instância de entidade carregada é manipulada como de costume, atribuindo uma propriedade .NET. O EF não está envolvido nesta etapa.
- Finalmente, DbContext.SaveChanges() é chamado. Neste ponto, o EF detecta automaticamente todas as alterações comparando as entidades com um instantâneo a partir do momento em que foram carregadas. Todas as alterações detectadas são mantidas no banco de dados; ao usar um banco de dados relacional, isso normalmente envolve o envio, por exemplo, de um SQL
UPDATEpara atualizar as linhas relevantes.
Observe que a descrição acima detalha uma operação de atualização típica para dados existentes, mas princípios semelhantes se aplicam para adicionar e remover entidades. Você interage com o rastreador de alterações do EF ao chamar DbSet<TEntity>.Add e Remove, fazendo com que as alterações sejam registradas. Em seguida, o EF aplica todas as alterações controladas ao banco de dados quando SaveChanges() é chamado (por exemplo, via SQL INSERT e DELETE ao usar um banco de dados relacional).
SaveChanges() oferece as seguintes vantagens:
- Você não precisa escrever código para controlar quais entidades e propriedades foram alteradas – o EF faz isso automaticamente para você e só atualiza essas propriedades no banco de dados, melhorando o desempenho. Imagine se suas entidades carregadas estiverem associadas a um componente de interface do usuário, permitindo que os usuários alterem qualquer propriedade desejada; O EF tira o fardo de descobrir quais entidades e propriedades foram realmente alteradas.
- Às vezes, salvar alterações no banco de dados pode ser complicado! Por exemplo, se você quiser adicionar um Blog e algumas Postagens para esse blog, talvez seja necessário buscar a chave gerada pelo banco de dados para o Blog inserido antes de inserir as Postagens (já que elas precisam se referir ao Blog). EF faz tudo isso por você, tirando a complexidade.
- O EF pode detectar problemas de simultaneidade, como quando uma linha de banco de dados foi modificada por outra pessoa entre sua consulta e SaveChanges(). Mais detalhes estão disponíveis em conflitos de concorrência.
- Em bancos de dados que dão suporte a ele, SaveChanges() encapsula automaticamente várias alterações em uma transação, garantindo que seus dados permaneçam consistentes se ocorrer uma falha. Mais detalhes estão disponíveis em Transações.
- SaveChanges() também, em muitos casos, agrupa várias alterações, reduzindo significativamente o número de consultas ao banco de dados e melhorando consideravelmente o desempenho. Mais detalhes estão disponíveis em Efficient updating.
Para obter mais informações e exemplos de código sobre o uso básico SaveChanges() , consulte Basic SaveChanges. Para obter mais informações sobre o controle de alterações do EF, consulte a visão geral do controle de alterações.
Abordagem 2: ExecuteUpdate e ExecuteDelete ("atualização em massa")
Embora o controle de alterações e SaveChanges() seja uma maneira poderosa de guardar modificações, ela tem certas desvantagens.
Primeiro, SaveChanges() requer que você consulte e acompanhe todas as entidades que modificará ou excluirá. Se você precisar, por exemplo, excluir todos os blogs com uma classificação abaixo de um determinado limite, deverá consultar, materializar e rastrear um número potencialmente enorme de linhas e ter SaveChanges() para gerar uma instrução DELETE para cada uma delas. Os bancos de dados relacionais fornecem uma alternativa muito mais eficiente: um único DELETE comando pode ser enviado, especificando quais linhas excluir por meio de uma WHERE cláusula, mas o SaveChanges() modelo não permite gerar isso.
Para dar suporte a esse cenário de "atualização em massa", você pode usar ExecuteDelete da seguinte maneira:
context.Blogs.Where(b => b.Rating < 3).ExecuteDelete();
Isso permite que você expresse uma instrução SQL DELETE por meio de operadores LINQ regulares , semelhantes a uma consulta LINQ regular, fazendo com que o seguinte SQL seja executado no banco de dados:
DELETE FROM [b]
FROM [Blogs] AS [b]
WHERE [b].[Rating] < 3
Isso é executado com muita eficiência no banco de dados, sem carregar dados do banco de dados ou envolver o rastreador de alterações do EF. Da mesma forma, ExecuteUpdate permite que você expresse uma instrução SQL UPDATE .
Mesmo que você não esteja alterando entidades em massa, talvez saiba exatamente quais propriedades de qual entidade você deseja alterar. Usar a API de controle de alterações para executar a alteração pode ser excessivamente complexo, exigindo a criação de uma instância de entidade, acompanhando-a via Attach, fazendo suas alterações e, por fim, chamando SaveChanges(). Para esses cenários, ExecuteUpdate e ExecuteDelete pode ser uma maneira consideravelmente mais simples de expressar a mesma operação.
Por fim, o controle de alterações e SaveChanges() em si impõem uma determinada sobrecarga de tempo de execução. Se você estiver escrevendo um aplicativo de alto desempenho, ExecuteUpdate e ExecuteDelete permitem que você evite esses dois componentes e gere com eficiência a instrução desejada.
No entanto, observe que ExecuteUpdate e ExecuteDelete também têm certas limitações:
- Esses métodos são executados imediatamente e atualmente não podem ser agrupados em lote com outras operações. Por outro lado, SaveChanges()pode agrupar várias operações em lote.
- Como o controle de alterações não está envolvido, é sua responsabilidade saber exatamente quais entidades e propriedades precisam ser alteradas. Isso pode significar um controle de código mais manual e de baixo nível do que precisa ser alterado e o que não muda.
- Além disso, como o controle de alterações não está envolvido, esses métodos não aplicam automaticamente o Controle de Simultaneidade ao persistir as alterações. No entanto, você ainda pode adicionar explicitamente uma
Wherecláusula para implementar o controle de simultaneidade por conta própria. - No momento, somente a atualização e a exclusão têm suporte; a inserção deve ser feita por meio de DbSet<TEntity>.Add e SaveChanges().
Para obter mais informações e exemplos de código, consulte ExecuteUpdate e ExecuteDelete.
Resumo
A seguir estão algumas diretrizes para quando usar qual abordagem. Observe que elas não são regras absolutas, mas fornecem regras úteis:
- Se você não souber com antecedência quais alterações ocorrerão, use
SaveChanges; ele detectará automaticamente quais alterações precisam ser aplicadas. Exemplos de cenários:- "Quero carregar um Blog do banco de dados e exibir um formulário permitindo que o usuário o altere"
- Se você precisar manipular um grafo de objetos (ou seja, vários objetos interconectados), use
SaveChanges; ele descobrirá a ordenação adequada das alterações e como vincular tudo.- "Quero atualizar um blog, alterar algumas de suas postagens e excluir outras"
- Se você quiser alterar um número potencialmente grande de entidades com base em algum critério, use
ExecuteUpdateeExecuteDelete. Exemplos de cenários:- "Quero dar um aumento a todos os funcionários"
- "Quero excluir todos os blogs cujo nome começa com X"
- Se você já sabe exatamente quais entidades deseja modificar e como deseja alterá-las, use
ExecuteUpdateeExecuteDelete. Exemplos de cenários:- "Quero excluir o blog cujo nome é 'Foo'"
- "Desejo alterar o nome do blog com a ID 5 para 'Barra'"