Excluir um único registro do Entity Framework?

195

Eu tenho uma tabela do SQL Server no Entity Framework denominada employcom uma coluna de chave única denominada ID.

Como excluo um único registro da tabela usando o Entity Framework?

user2497476
fonte
2
db.employ.Remove (db.employ.Find (ID1))
Carter Medlin
2
@CarterMedlin - enquanto isso funcionará, são dois acertos no banco de dados: um SELECT e um DELETE. A maioria das pessoas acha isso extremamente inútil, principalmente porque o select provavelmente levará muito mais tempo do que uma exclusão.
Davor
Eu não sugeriria usar o framework de entidade Remove ou RemoveRange devido a problemas de desempenho. Prefiro usar algo super simples da seguinte forma: var sql = "DELETE FROM YOUR_TABLE WHERE YOUR_FIELD = @your_parameter"; this.your_context.Database.ExecuteSqlCommand (sql, new SqlParameter ("@ your_parameter", yourParameter));
precisa saber é o seguinte
2
@curiousBoy Acho que quando você executa instruções como sugeriu, o cache EF6 não reflete a alteração.
Yitzchak

Respostas:

362

Não é necessário consultar o objeto primeiro, você pode anexá-lo ao contexto por seu ID. Como isso:

var employer = new Employ { Id = 1 };
ctx.Employ.Attach(employer);
ctx.Employ.Remove(employer);
ctx.SaveChanges();

Como alternativa, você pode definir o estado da entrada anexada como excluído:

var employer = new Employ { Id = 1 };
ctx.Entry(employer).State = EntityState.Deleted;
ctx.SaveChanges();
mt_serg
fonte
87
Em alternativa,ctx.Entry(employer).State = EntityState.Deleted
Simon Belanger
12
isso funcionará apenas se os relacionamentos forem definidos como cascata de exclusão. caso contrário, o código acima falhará em uma exceção FK.
precisa saber é o seguinte
6
@mt_serg, estou olhando três passos à frente. quando foi a última vez que você realmente removeu um registro tão simples do banco de dados? normalmente você está lidando com registros mais complexos que incluem relações FK. daqui meu comentário.
precisa saber é o seguinte
2
@IanWarburton A 2ª e a 3ª linha (Anexar e Remover)
Simon Belanger
4
@PaulZahra: às vezes você tem uma lista de IDs de alguma outra consulta ou fonte e precisa excluir um. Em vez de carregar os objetos apenas para excluí-los, é possível excluir por ID. Você sabe, é assim que a instrução DELETE funciona normalmente no SQL.
siride
82

Você pode usar SingleOrDefaultpara obter um único objeto que corresponda aos seus critérios e depois passar para o Removemétodo da sua tabela EF.

var itemToRemove = Context.Employ.SingleOrDefault(x => x.id == 1); //returns a single item.

if (itemToRemove != null) {
    Context.Employ.Remove(itemToRemove);
    Context.SaveChanges();
}
Mansfield
fonte
5
esse não é um bom caminho, porque você seleciona todos os campos do banco de dados!
Ali Yousefi
2
É assim que eu faço.
Jack Fairfield
4
@ Ali, Jack - Mas acho que é preferível, porque primeiro verifica se os dados que você está tentando excluir realmente existem, o que pode impedir qualquer problema. A resposta aceita não tem verificação como tal.
Michael Philips
4
Este é o melhor caminho. Pense nisso. E se John Smith estiver tentando remover um item com um ID = 1 que Susie Smith removeu 30 segundos atrás, mas John não sabe? Você precisa acessar o banco de dados nesse caso.
Yusha
4
@Yusha Why? Nos dois cenários, o resultado é que o registro se foi. Nós realmente nos importamos se isso aconteceu agora ou 30 segundos atrás? Algumas condições de corrida simplesmente não são tão interessantes para acompanhar.
9Rune5
13
  var stud = (from s1 in entities.Students
            where s1.ID== student.ID
            select s1).SingleOrDefault();

  //Delete it from memory
  entities.DeleteObject(stud);
  //Save to database
  entities.SaveChanges();
Alex G
fonte
2
FirstOrDefaulté perigoso. Ou você sabe que há apenas um (use-o SingleOrDefault) ou há mais de um, e isso deve ser feito em um loop.
Mark Sowul
8
Employer employer = context.Employers.First(x => x.EmployerId == 1);

context.Customers.DeleteObject(employer);
context.SaveChanges();
Sam Leach
fonte
Isso protege se não houver objeto com o ID 1? Não lançaria uma exceção?
Jack Fairfield
@JackFairfield eu acho que você deve verificar se há objeto nulo. e de acordo com ele executar remover.
perfil completo de Jawand Singh
Firsté perigoso. Ou você sabe que há apenas um (use-o Single) ou há mais de um, e isso deve ser feito em um loop.
Mark Sowul
5

Estou usando a estrutura da entidade com o LINQ. O código a seguir foi útil para mim;

1- Para vários registros

 using (var dbContext = new Chat_ServerEntities())
 {
     var allRec= dbContext.myEntities;
     dbContext.myEntities.RemoveRange(allRec);
     dbContext.SaveChanges();
 }

2- Para registro único

 using (var dbContext = new Chat_ServerEntities())
 {
     var singleRec = dbContext.ChatUserConnections.FirstOrDefault( x => x.ID ==1);// object your want to delete
     dbContext.ChatUserConnections.Remove(singleRec);
     dbContext.SaveChanges();
 }
Baqer Naqvi
fonte
Para registro único, por que não usar em SingleOrDefaultvez de FirstOrDefault?
Mark Sowul
Sempre que você usa o SingleOrDefault, você afirma claramente que a consulta deve resultar no máximo em um único resultado. Por outro lado, quando FirstOrDefault é usado, a consulta pode retornar qualquer quantidade de resultados, mas você afirma que deseja apenas o primeiro stackoverflow.com/a/1745716/3131402
Baqer Naqvi
1
Sim, então por que seria correto excluir um registro arbitrário, se houver mais de um? Particularmente neste caso, o ID é a chave, por isso não deve ser uma: se houver mais de um, é um bug (que Individual detectaria)
Mark Sowul
@ MarkSowul você está certo. Eu editei a resposta para usar o FirstOrDefault.
Baqer Naqvi
@BaqerNaqvi RemoveRange é uma maneira terrível de remover a entidade da perspectiva de desempenho. Especialmente quando sua entidade está pesada com todas as propriedades de navegação por chaves estrangeiras. Prefiro usar var sql = "DELETE FROM YOUR_TABLE WHERE YOUR_FIELD = @seu_parâmetro"; this.your_context.Database.ExecuteSqlCommand (sql, new SqlParameter ("@ your_parameter", yourParameter));
precisa saber é o seguinte
2

Aprovação mais genérica

public virtual void Delete<T>(int id) where T : BaseEntity, new()
{
    T instance = Activator.CreateInstance<T>();
    instance.Id = id;
    if (dbContext.Entry<T>(entity).State == EntityState.Detached)
    {
        dbContext.Set<T>().Attach(entity);
    }

    dbContext.Set<T>().Remove(entity);
}
valentasm
fonte
2

Com o Entity Framework 6, você pode usar Remove. Também é uma boa tática a ser usada usingpara ter certeza de que sua conexão está fechada.

using (var context = new EmployDbContext())
{
    Employ emp = context.Employ.Where(x => x.Id == id).Single<Employ>();
    context.Employ.Remove(emp);
    context.SaveChanges();
}
Gizmo
fonte
1

Só queria contribuir com os três métodos com os quais eu andei.

Método 1:

var record = ctx.Records.FirstOrDefault();
ctx.Records.Remove(record);
ctx.SaveChanges();

Método 2:

var record = ctx.Records.FirstOfDefault();
ctx.Entry(record).State = EntityState.Deleted;
ctx.SaveChanges();
ctx.Entry(record).State = EntityState.Detached;

Uma das razões pelas quais eu prefiro seguir o método 2 é porque, no caso de definir EF ou EFCore QueryTrackingBehavior.NoTracking, é mais seguro fazer isso.

Depois, há o método 3:

var record = ctx.Records.FirstOrDefault();
var entry = ctx.Entry(record);
record.DeletedOn = DateTimeOffset.Now;
entry.State = EntityState.Modified;
ctx.SaveChanges();
entry.State = EntityState.Detached;

Isso utiliza uma abordagem de exclusão suave, definindo a DeletedOnpropriedade do registro e ainda sendo capaz de manter o registro para uso futuro, qualquer que seja. Basicamente, colocá-lo na Lixeira .


Além disso, em relação ao método 3 , em vez de definir o registro inteiro para ser modificado:

entry.State = EntityState.Modified;

Você também definiria apenas a coluna DeletedOncomo modificada:

entry.Property(x => x.DeletedOn).IsModified = true;
LatentDenis
fonte
0
    [HttpPost]
    public JsonResult DeleteCotnact(int id)
    {
        using (MycasedbEntities dbde = new MycasedbEntities())
        {
            Contact rowcontact = (from c in dbde.Contact
                                     where c.Id == id
                                     select c).FirstOrDefault();

            dbde.Contact.Remove(rowcontact);
            dbde.SaveChanges();

            return Json(id);
        }
    }

O que você acha disso, simples ou não, você também pode tentar o seguinte:

        var productrow = cnn.Product.Find(id);
        cnn.Product.Remove(productrow);
        cnn.SaveChanges();
Namroy
fonte
0

Para o DAO genérico, meu trabalho finalmente é o seguinte:

    public void Detele(T entity)
    {
        db.Entry(entity).State = EntityState.Deleted;
        db.SaveChanges();
    }
Tom Trnka
fonte
0

Usar EntityFramework.Plus pode ser uma opção:

dbContext.Employ.Where(e => e.Id == 1).Delete();

Mais exemplos estão disponíveis aqui

Mohammad Reza Sadreddini
fonte
0

você pode fazer isso simplesmente assim

   public ActionResult Delete(int? id)
    {
        using (var db = new RegistrationEntities())
        {
            Models.RegisterTable Obj = new Models.RegisterTable();
            Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
            if (personalDetail == null)
            {
                return HttpNotFound();
            }
            else
            {
                Obj.UserID = personalDetail.UserID;
                Obj.FirstName = personalDetail.FName;
                Obj.LastName = personalDetail.LName;
                Obj.City = personalDetail.City;

            }
            return View(Obj);
        }
    }


    [HttpPost, ActionName("Delete")]

    public ActionResult DeleteConfirmed(int? id)
    {
        using (var db = new RegistrationEntities())
        {
            Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
            db.RegisterDbTable.Remove(personalDetail);
            db.SaveChanges();
            return RedirectToAction("where u want it to redirect");
        }
    }

modelo

 public class RegisterTable
{

    public int UserID
    { get; set; }


    public string FirstName
    { get; set; }


    public string LastName
    { get; set; }


    public string Password
    { get; set; }


    public string City
    { get; set; }

} 

vista a partir do qual você vai chamá-lo

 <table class="table">
    <tr>
        <th>
            FirstName
        </th>
        <th>
            LastName
        </th>

        <th>
            City
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td> @item.FirstName </td>
            <td> @item.LastName </td>
            <td> @item.City</td>
            <td>
                <a href="@Url.Action("Edit", "Registeration", new { id = item.UserID })">Edit</a> |
                <a href="@Url.Action("Details", "Registeration", new { id = item.UserID })">Details</a> |
                <a href="@Url.Action("Delete", "Registeration", new { id = item.UserID })">Delete</a>

            </td>
        </tr>

    }

</table>

Espero que seja fácil para você entender

Sikander Iqbal
fonte
0

Você pode fazer algo assim no seu evento de clique ou clique de célula da sua grade (se você usou um)

if(dgEmp.CurrentRow.Index != -1)
 {
    employ.Id = (Int32)dgEmp.CurrentRow.Cells["Id"].Value;
    //Some other stuff here
 }

Em seguida, faça algo assim no seu botão Excluir:

using(Context context = new Context())
{
     var entry = context.Entry(employ);
     if(entry.State == EntityState.Detached)
     {
        //Attached it since the record is already being tracked
        context.Employee.Attach(employ);
     }                             
     //Use Remove method to remove it virtually from the memory               
     context.Employee.Remove(employ);
     //Finally, execute SaveChanges method to finalized the delete command 
     //to the actual table
     context.SaveChanges();

     //Some stuff here
}

Como alternativa, você pode usar uma consulta LINQ em vez de usar a consulta LINQ To Entities:

var query = (from emp in db.Employee
where emp.Id == employ.Id
select emp).Single();

Employ.Id é usado como parâmetro de filtragem que já foi passado do CellDoubleClick Event do seu DataGridView.

arvin aquio
fonte
A idéia por trás do código é conectar o ID (Employ.Id) do registro que você deseja excluir ao modelo (Employee Class) e, em seguida, anexá-lo à tabela real do contexto, em seguida, executar o método Remove () na memória e finalmente, execute o salvamento real no banco de dados usando o método SaveChanges (). Embora a consulta LINQ também funcione bem, mas não gosto da ideia de consultar a tabela apenas para obter o ID do registro.
Arvin aquio
0

Aqui está uma maneira segura:

using (var transitron = ctx.Database.BeginTransaction())
{
  try
  {
    var employer = new Employ { Id = 1 };
    ctx.Entry(employer).State = EntityState.Deleted;
    ctx.SaveChanges();
    transitron.Commit();
  }
  catch (Exception ex)
  {
    transitron.Rollback();
    //capture exception like: entity does not exist, Id property does not exist, etc...
  }
}

Aqui você pode acumular todas as alterações que desejar, para fazer uma série de exclusão antes de SaveChanges e Commit, para que elas sejam aplicadas apenas se tiverem êxito.

Emilio.NT
fonte
0

A melhor maneira é verificar e excluir

        if (ctx.Employ.Any(r=>r.Id == entity.Id))
        {
            Employ rec = new Employ() { Id = entity.Id };
            ctx.Entry(rec).State = EntityState.Deleted;
            ctx.SaveChanges();
        }
Fonte dE
fonte