Eliminare un singolo record da Entity Framework?


195

Ho una tabella di SQL Server in Entity Framework denominata employcon una colonna chiave singola denominata ID.

Come posso eliminare un singolo record dalla tabella usando Entity Framework?


2
db.employ.Remove (db.employ.Find (ID1))
Carter Medlin

2
@CarterMedlin - mentre funzionerà, questi sono due hit di database: uno SELECT e uno DELETE. Molte persone lo trovano estremamente dispendioso, soprattutto perché la selezione richiederà probabilmente molto più tempo di una cancellazione.
Assapora il

Non consiglierei di utilizzare il framework di entità Remove o RemoveRange a causa di problemi di prestazioni. Preferirei semplicemente usare qualcosa di super semplice come segue: var sql = "ELIMINA DA YOUR_TABLE DOVE YOUR_FIELD = @your_parameter"; this.your_context.Database.ExecuteSqlCommand (sql, new SqlParameter ("@ your_parameter", yourParameter));
curiousBoy

2
@curiousBoy Penso che quando esegui le istruzioni come hai suggerito, la cache EF6 non riflette la modifica.
Yitzchak,

Risposte:


362

Non è necessario prima interrogare l'oggetto, è possibile collegarlo al contesto tramite il suo ID. Come questo:

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

In alternativa, è possibile impostare lo stato della voce allegata su eliminato:

var employer = new Employ { Id = 1 };
ctx.Entry(employer).State = EntityState.Deleted;
ctx.SaveChanges();

87
In alternativa,ctx.Entry(employer).State = EntityState.Deleted
Simon Belanger

12
questo funzionerà solo se le relazioni sono definite come elimina cascata. in caso contrario il codice sopra riportato non riuscirà su un'eccezione FK.
Baruchl,

6
@mt_serg, sto guardando 3 passi avanti. quando è stata l'ultima volta che hai dovuto rimuovere un record così semplice dal database? di solito hai a che fare con record più complessi che includono relazioni FK. da qui il mio commento.
baruchl

2
@IanWarburton La 2a e 3a riga (Allega e Rimuovi)
Simon Belanger

4
@PaulZahra: a volte hai un elenco di ID da qualche altra query o fonte e devi eliminarne uno. Invece di caricare gli oggetti solo per eliminarli, in questo modo è possibile eliminare per ID. Sai, è così che funziona normalmente l'istruzione DELETE in SQL.
siride,

82

È possibile utilizzare SingleOrDefaultper ottenere un singolo oggetto corrispondente ai propri criteri, quindi passarlo al Removemetodo della tabella EF.

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

if (itemToRemove != null) {
    Context.Employ.Remove(itemToRemove);
    Context.SaveChanges();
}

5
questo non è un buon modo, perché si seleziona tutto il campo dal database!
Ali Yousefi,

2
Questo è il modo in cui lo faccio.
Jack Fairfield,

4
@Ali, Jack - Ma penso che sia preferibile perché controlla prima se i dati che stai cercando di eliminare effettivamente esistono che possono prevenire qualsiasi problema. La risposta accettata non ha alcun controllo in quanto tale.
Michael Philips,

4
Questo è il modo migliore Pensaci. E se John Smith stesse cercando di rimuovere un oggetto con un id = 1 che Susie Smith ha rimosso 30 secondi fa ma John non sa? È necessario colpire il database in quel caso.
Yusha,

4
@Yusha Why? In entrambi gli scenari il risultato è che il record è sparito. Ci interessa davvero se è successo ora o 30 secondi fa? Alcune condizioni di gara non sono poi così interessanti da tenere traccia.
9une 5

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();

2
FirstOrDefaultè pericoloso. O sai che ce n'è solo uno (quindi usa SingleOrDefault), o ce n'è più di uno e dovrebbe essere fatto in un ciclo.
Mark Sowul,

8
Employer employer = context.Employers.First(x => x.EmployerId == 1);

context.Customers.DeleteObject(employer);
context.SaveChanges();

Questo protegge se non ci sono oggetti con ID 1? Non sarebbe un'eccezione?
Jack Fairfield,

@JackFairfield penso che dovresti controllare l'oggetto null. e secondo esso eseguire rimuovere.
Jawand Singh,

Firstè pericoloso. O sai che ce n'è solo uno (quindi usa Single), o ce n'è più di uno e dovrebbe essere fatto in un ciclo.
Mark Sowul,

5

Sto usando il framework di entità con LINQ. Il seguente codice mi è stato utile;

1- Per più record

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

2- Per record singolo

 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();
 }

Per record singolo, perché non utilizzare SingleOrDefaultinvece di FirstOrDefault?
Mark Sowul,

Ogni volta che usi SingleOrDefault, dichiari chiaramente che la query dovrebbe generare al massimo un singolo risultato. D'altra parte, quando si utilizza FirstOrDefault, la query può restituire qualsiasi quantità di risultati ma si afferma che si desidera solo il primo stackoverflow.com/a/1745716/3131402
Baqer Naqvi

1
Sì, quindi perché sarebbe corretto eliminare un record arbitrario, se ce n'è più di uno? Soprattutto in questo caso l'id è la chiave, quindi dovrebbe
essercene

@MarkSowul hai ragione. Ho modificato la risposta per utilizzare FirstOrDefault.
Baqer Naqvi

@BaqerNaqvi RemoveRange è un modo terribile per rimuovere un'entità dal punto di vista delle prestazioni .. Soprattutto quando l'entità è pesante con tutte le proprietà di navigazione con chiavi esterne. Preferirei usare var sql = "DELETE FROM YOUR_TABLE DOVE YOUR_FIELD = @your_parameter"; this.your_context.Database.ExecuteSqlCommand (sql, new SqlParameter ("@ your_parameter", yourParameter));
curiousBoy

2

Approvuch più generico

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);
}

2

Con Entity Framework 6, è possibile utilizzare Remove. Inoltre è una buona tattica da usare usingper essere sicuri che la tua connessione sia chiusa.

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

1

Volevo solo contribuire con i tre metodi con cui sono rimbalzato avanti e indietro.

Metodo 1:

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

Metodo 2:

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

Uno dei motivi per cui preferisco seguire il metodo 2 è perché nel caso di impostare EF o EFCore su QueryTrackingBehavior.NoTracking, è più sicuro farlo.

Quindi c'è il metodo 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;

Questo utilizza un approccio di eliminazione graduale impostando la DeletedOnproprietà del record ed essendo ancora in grado di conservare il record per uso futuro, qualunque cosa possa essere. Fondamentalmente, mettendolo nel Cestino .


Inoltre, per quanto riguarda il Metodo 3 , invece di impostare l'intero record da modificare:

entry.State = EntityState.Modified;

Dovresti semplicemente impostare solo la colonna DeletedOncome modificata:

entry.Property(x => x.DeletedOn).IsModified = true;

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);
        }
    }

Cosa ne pensi di questo, semplice o no, potresti anche provare questo:

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

0

Per il DAO generico il mio lavoro alla fine è questo:

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


0

puoi farlo semplicemente così

   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");
        }
    }

modello

 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 da cui lo chiamerai

 <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>

spero che questo sia facile da capire


0

Puoi fare qualcosa del genere nel tuo evento click o celldoubleclick della tua griglia (se ne hai usato uno)

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

Quindi fai qualcosa del genere nel tuo pulsante Elimina:

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
}

In alternativa, è possibile utilizzare una query LINQ anziché utilizzare la query LINQ To Entities:

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

impiegato.Id viene utilizzato come parametro di filtro che è già stato passato dall'evento CellDoubleClick di DataGridView.


L'idea alla base del codice è collegare l'id (Employ.Id) del record che si desidera eliminare al modello (classe Employee) e quindi collegarlo alla tabella effettiva dal contesto, quindi eseguire il metodo Remove () in memoria quindi eseguire infine il salvataggio effettivo nel database utilizzando il metodo SaveChanges (). Anche se la query LINQ funziona bene, ma non mi piace l'idea di interrogare la tabella solo per ottenere l'ID del record.
Arvin Aquio,

0

Ecco un modo sicuro:

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...
  }
}

Qui puoi accumulare tutte le modifiche che desideri, quindi puoi fare una serie di eliminazioni prima di SaveChanges e Commit, in modo che vengano applicate solo se tutte hanno esito positivo.


0

Il modo migliore è controllare e quindi eliminare

        if (ctx.Employ.Any(r=>r.Id == entity.Id))
        {
            Employ rec = new Employ() { Id = entity.Id };
            ctx.Entry(rec).State = EntityState.Deleted;
            ctx.SaveChanges();
        }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.