Il me semble que je dois récupérer un objet avant de le supprimer avec un framework d'entité comme ci-dessous
var customer = context.Customers.First(c => c.Id == 1);
context.DeleteObject(customer);
context.Savechanges();
J'ai donc besoin de frapper la base de données deux fois. Y a-t-il un moyen plus facile?
Dans Entity Framework 6, l'action de suppression est Remove
. Voici un exemple
Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.Remove(customer);
context.SaveChanges();
Identique à @Nix avec une petite modification à être fortement typée:
Si vous ne voulez pas interroger, créez simplement une entité, puis supprimez-la.
Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.DeleteObject(customer);
context.SaveChanges();
Question similaire ici .
Avec Entity Framework, il y a EntityFramework-Plus (bibliothèque d'extensions).
Disponible sur NuGet. Ensuite, vous pouvez écrire quelque chose comme:
// DELETE all users which has been inactive for 2 years
ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2))
.Delete();
C'est également utile pour les suppressions en masse.
Si vous ne voulez pas l'interroger, créez simplement une entité, puis supprimez-la.
Customer customer = new Customer() { Id = 1 } ;
context.AttachTo("Customers", customer);
context.DeleteObject(customer);
context.Savechanges();
J'utilise le code suivant dans l'un de mes projets:
using (var _context = new DBContext(new DbContextOptions<DBContext>()))
{
try
{
_context.MyItems.Remove(new MyItem() { MyItemId = id });
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
if (!_context.MyItems.Any(i => i.MyItemId == id))
{
return NotFound();
}
else
{
throw ex;
}
}
}
De cette façon, la base de données ne sera interrogée que deux fois si une exception se produit lors de la tentative de suppression de l'élément avec l'ID spécifié. Ensuite, si l'élément n'est pas trouvé, il renvoie un message significatif. sinon, il renvoie simplement l'exception (vous pouvez gérer cela d'une manière plus adaptée à votre cas en utilisant différents blocs catch pour différents types d'exceptions, ajoutez davantage de contrôles personnalisés en utilisant des blocs if, etc.).
[J'utilise ce code dans un projet MVC .Net Core/.Net Core avec Entity Framework Core.]
Une requête sql brute est le moyen le plus rapide, je suppose
public void DeleteCustomer(int id)
{
using (var context = new Context())
{
const string query = "DELETE FROM [dbo].[Customers] WHERE [id]={0}";
var rows = context.Database.ExecuteSqlCommand(query,id);
// rows >= 1 - count of deleted rows,
// rows = 0 - nothing to delete.
}
}
la réponse de dwkd a principalement fonctionné pour moi dans le noyau Entity Framework, sauf lorsque j'ai vu cette exception:
InvalidOperationException: l'instance du type d'entité 'Client' ne peut pas être suivie car une autre instance avec la même valeur de clé pour {'Id'} est déjà suivie. Lorsque vous attachez des entités existantes, assurez-vous qu'une seule instance d'entité avec une valeur de clé donnée est attachée. Pensez à utiliser 'DbContextOptionsBuilder.EnableSensitiveDataLogging' pour voir les valeurs de clé en conflit.
Pour éviter l'exception, j'ai mis à jour le code:
Customer customer = context.Customers.Local.First(c => c.Id == id);
if (customer == null) {
customer = new Customer () { Id = id };
context.Customers.Attach(customer);
}
context.Customers.Remove(customer);
context.SaveChanges();
Si vous utilisez EF 1.0, c'est la façon la plus concise de le faire. Il y a peut-être d'autres moyens, mais ils sont plus problématiques qu'ils ne valent la peine, à mon humble avis.