Estou excluindo vários itens de uma tabela usando o Entity Framework. Não existe uma chave estrangeira / objeto pai, portanto não posso lidar com isso com o OnDeleteCascade.
Agora eu estou fazendo isso:
var widgets = context.Widgets
.Where(w => w.WidgetId == widgetId);
foreach (Widget widget in widgets)
{
context.Widgets.DeleteObject(widget);
}
context.SaveChanges();
Funciona, mas o foreach me incomoda. Estou usando EF4, mas não quero executar SQL. Eu só quero ter certeza de que não estou perdendo nada - isso é o melhor possível, certo? Eu posso abstraí-lo com um método de extensão ou auxiliar, mas em algum lugar ainda vamos fazer um foreach, certo?
entity-framework
Jon Galloway
fonte
fonte
Respostas:
Se você não deseja executar o SQL diretamente, chamando DeleteObject em um loop é o melhor que você pode fazer hoje.
No entanto, você pode executar o SQL e ainda torná-lo de propósito geral por meio de um método de extensão, usando a abordagem descrita aqui .
Embora essa resposta fosse para 3,5. Para a versão 4.0, eu provavelmente usaria a nova API ExecuteStoreCommand sob o capô, em vez de ir para o StoreConnection.
fonte
O EntityFramework 6 tornou isso um pouco mais fácil
.RemoveRange()
.Exemplo:
fonte
Bem, sim, exceto que você pode transformá-lo em duas linhas:
fonte
fonte
WHERE IN ({0})
o segundo argumento deve serString.Join(",", idList)
.EntityFramework.Extended
String.Join
, pode ser necessário usarstring.Format
e passar a string SQL já formada para o comando. Desde que sua lista tenha apenas números inteiros, não há risco de ataque por injeção. Verifique esta pergunta: como posso passar uma matriz para um comando execute store?Eu sei que é muito tarde, mas, caso alguém precise de uma solução simples, o interessante é que você também pode adicionar a cláusula where com ela:
Nota: apenas testado com MSSQL2008.
Atualizar:
A solução acima não funcionará quando EF gerar instrução sql com parâmetros , então aqui está a atualização para EF5 :
Requer um pouco de reflexão, mas funciona bem.
fonte
Para quem usa o EF5, a seguinte biblioteca de extensões pode ser usada: https://github.com/loresoft/EntityFramework.Extended
fonte
Delete()
função em minhas entidades no EF6.context.Widgets.Where(w => w.WidgetId == widgetId).Delete();
é a maneira mais recente com EntityFramework.ExtendedAinda parece uma loucura ter que retirar qualquer coisa do servidor apenas para excluí-lo, mas pelo menos recuperar apenas os IDs é muito mais enxuto do que remover as entidades completas:
fonte
Widget
objetos stub têm apenas umaId
propriedade inicializada . A maneira de contornar isso é usarcontext.Configuration.ValidateOnSaveEnabled = false
(pelo menos no EF6). Isso desativa a validação própria do Entity Framework, mas ainda executa a validação própria do banco de dados, é claro.delete
com uma solução semelhante paraupdate
ing entidades sem carregá-los.EF 6.1
Uso:
fonte
Para o EF 4.1,
fonte
Você pode usar as bibliotecas de extensões para fazer isso, como EntityFramework.Extended ou Z.EntityFramework.Plus.EF6, existem disponíveis para EF 5, 6 ou Core. Essas bibliotecas têm ótimo desempenho quando você precisa excluir ou atualizar e usa o LINQ. Exemplo para excluir ( fonte mais ):
ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2)) .Delete();
ou ( fonte estendida )
context.Users.Where(u => u.FirstName == "firstname") .Delete();
Eles usam instruções SQL nativas, portanto, o desempenho é ótimo.
fonte
A maneira mais rápida de excluir é usando um procedimento armazenado. Eu prefiro procedimentos armazenados em um projeto de banco de dados em vez de SQL dinâmico, porque as renomeações serão tratadas corretamente e terão erros de compilador. O SQL dinâmico pode se referir a tabelas que foram excluídas / renomeadas, causando erros em tempo de execução.
Neste exemplo, eu tenho duas tabelas List e ListItems. Eu preciso de uma maneira rápida de excluir todos os ListItems de uma determinada lista.
Agora, a parte interessante de excluir os itens e atualizar a estrutura do Entity usando uma extensão.
O código principal agora pode ser usado como
fonte
Se você deseja excluir todas as linhas de uma tabela, você pode executar o comando sql
TRUNCATE TABLE (Transact-SQL) Remove todas as linhas de uma tabela sem registrar as exclusões de linhas individuais. TRUNCATE TABLE é semelhante à instrução DELETE sem a cláusula WHERE; no entanto, TRUNCATE TABLE é mais rápido e usa menos recursos do sistema e do log de transações.
fonte
truncate table
em tabelas que são referenciadas por uma restrição FOREIGN KEY. (Você pode truncar uma tabela que tenha uma chave estrangeira que faça referência a si mesma.). Documentação MSDNUUHHIVS
é uma maneira muito elegante e rápida de excluir lotes, mas deve ser usada com cuidado:context.SaveChanges()
Esses problemas podem ser contornados assumindo o controle da transação. O código a seguir ilustra como excluir em lotes e inserir em massa de maneira transacional:
fonte
Entidade da estrutura da entidade
Resumo :
Observações :
fonte
Você pode executar consultas sql diretamente da seguinte maneira:
Para selecionar, podemos usar
fonte
Você também pode usar o método DeleteAllOnSubmit () passando seus resultados em uma lista genérica em vez de em var. Dessa forma, seu foreach se reduz a uma linha de código:
Provavelmente ainda usa um loop internamente.
fonte
var
é isso.A resposta de Thanh funcionou melhor para mim. Excluiu todos os meus registros em uma única viagem de servidor. Eu lutei para realmente chamar o método de extensão, então pensei em compartilhar o meu (EF 6):
Adicionei o método de extensão a uma classe auxiliar no meu projeto MVC e alterei o nome para "RemoveWhere". Injeto um dbContext nos meus controladores, mas você também pode fazer um
using
.Isso gerou uma única instrução de exclusão para o grupo.
fonte
EF 6. =>
fonte
Melhor :
in EF6 => .RemoveRange()
Exemplo:
fonte
Veja a resposta 'código favorito' que funciona
Aqui está como eu o usei:
fonte
No EF 6.2, isso funciona perfeitamente, enviando a exclusão diretamente para o banco de dados sem primeiro carregar as entidades:
Com um predicado fixo, é bastante direto:
E se você precisar de um predicado dinâmico, dê uma olhada no LINQKit (pacote Nuget disponível), algo assim funciona bem no meu caso:
fonte
Z.EntityFramework.Plus
ou algo parecido? ( Entityframework.net/batch-delete )Delete()
método é inerentemente inexistente).