Entity Framework'ten tek bir kayıt silinsin mi?


195

Entity Framework adlı employtek bir anahtar sütun adlı bir SQL Server tablo var ID.

Entity Framework kullanarak tablodan tek bir kaydı nasıl silebilirim?


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

2
@CarterMedlin - bu işe yarayacak olsa da, bunlar iki veritabanı isabetidir: bir SELECT ve bir DELETE. Çoğu insan, özellikle seçimin bir silme işleminden önemli ölçüde daha fazla zaman alacağından, son derece israflı olduğunu düşünüyor.
Davor

Performans sorunları nedeniyle Remove veya RemoveRange varlık çerçevesinin kullanılmasını önermem. Ben sadece aşağıdaki gibi süper basit bir şey kullanmak istiyorum: var sql = "YOUR_TABLE NEREDEN NEREDEN YOUR_FIELD = @ your_parameter"; this.your_context.Database.ExecuteSqlCommand (sql, yeni SqlParameter ("@ parametreniz", parametreniz));
curiousBoy

2
@curiousBoy Önerilen ifadeleri çalıştırdığınızda EF6 önbelleğinin değişikliği yansıtmayacağını düşünüyorum.
Yitzchak

Yanıtlar:


362

İlk olarak nesneyi sorgulamak gerekli değildir, onu kimliğe göre bağlama ekleyebilirsiniz. Bunun gibi:

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

Alternatif olarak, ekli girişin durumunu silinecek şekilde ayarlayabilirsiniz:

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

87
Alternatif olarak,ctx.Entry(employer).State = EntityState.Deleted
Simon Belanger

12
bu yalnızca ilişkiler silme dizisi olarak tanımlanırsa çalışır. aksi takdirde yukarıdaki kod bir FK istisnasında başarısız olur.
baruchl

6
@mt_serg, 3 adım ileri bakıyorum. En son ne zaman DB'den bu kadar basit bir kaydı silmek zorunda kaldınız? genellikle FK ilişkilerini içeren daha karmaşık kayıtlarla uğraşıyorsunuz. dolayısıyla benim yorumum.
14'te baruchl

2
@IanWarburton 2. ve 3. satır (Tak ve Kaldır)
Simon Belanger

4
@PaulZahra: bazen başka bir sorgu veya kaynaktan gelen kimliklerin bir listesi vardır ve birini silmeniz gerekir. Nesneleri yalnızca silmek için yüklemek yerine, bu şekilde kimliğe göre silebilirsiniz. Bilirsiniz, DELETE deyimi normalde SQL'de böyle çalışır.
siride

82

Sen kullanabilirsiniz SingleOrDefaultsenin kriterleri Tek bir nesneyi almak için ve sonra o geçmesi RemoveEF tablosu yöntemiyle.

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

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

5
Bu iyi bir yol değildir, çünkü veritabanından tüm alanları seçersiniz!
Ali Yousefi

2
Ben böyle yapıyorum.
Jack Fairfield

4
@Ali, Jack - Ama bence bu tercih edilebilir çünkü öncelikle silmeye çalıştığınız verilerin gerçekte var olup olmadığını kontrol eder ve bu da herhangi bir sorunu önleyebilir. Kabul edilen cevabın böyle bir kontrolü yoktur.
Michael Philips

4
Bu daha iyi bir yol. Bunu düşün. John Smith, Susie Smith'in 30 saniye önce kaldırdığı ancak John'un bilmediği bir = 1 kimliğine sahip bir öğeyi kaldırmaya çalışıyorsa ne olur? Bu durumda veritabanına vurmanız gerekir.
Yusha

5
@Yusha Neden? Her iki senaryoda da sonuç kaydın kaybolmasıdır. Bunun şimdi mi yoksa 30 saniye önce mi olduğunu gerçekten umursuyor muyuz? Bazı yarış koşulları takip etmek o kadar da ilginç değil.
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();

2
FirstOrDefaulttehlikeli. Ya sadece bir tane olduğunu (yani kullanın SingleOrDefault) biliyorsunuz ya da birden fazla var ve bir döngü içinde yapılmalıdır.
Mark Sowul

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

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

Kimlik 1 ile bir nesne yoksa bu koruma sağlar mı? İstisna atmaz mı?
Jack Fairfield

@JackFairfield boş nesne olup olmadığını kontrol etmeniz gerektiğini düşünüyorum. ve buna göre kaldırma işlemini gerçekleştirin.
Jawand Singh

Firsttehlikeli. Ya sadece bir tane olduğunu (yani kullanın Single) biliyorsunuz ya da birden fazla var ve bir döngü içinde yapılmalıdır.
Mark Sowul

5

LINQ ile varlık çerçevesini kullanıyorum. Aşağıdaki kod benim için yararlı oldu;

1- Birden fazla kayıt için

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

2- Tek kayıt için

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

Tek kayıt için neden SingleOrDefaultbunun yerine kullanılmıyor FirstOrDefault?
Mark Sowul

SingleOrDefault'u her kullandığınızda, sorgunun en fazla tek bir sonuçla sonuçlanması gerektiğini açıkça belirtirsiniz. Öte yandan, FirstOrDefault kullanıldığında, sorgu herhangi bir miktarda sonuç döndürebilir, ancak yalnızca ilkini istediğinizi belirtirsiniz stackoverflow.com/a/1745716/3131402
Baqer Naqvi

1
Evet, peki birden fazla varsa rasgele bir kaydı silmek neden doğru olur? Özellikle bu durumda kimlik anahtardır, bu yüzden bir tane olmalıdır: birden fazla varsa, bu bir hatadır (Single'ın tespit edeceği)
Mark Sowul

@MarkSowul haklısın. FirstOrDefault kullanmak için cevabı düzenledim.
Baqer Naqvi

@BaqerNaqvi RemoveRange, varlığı performans perspektifinden kaldırmanın korkunç bir yoludur. Özellikle de varlığınız yabancı navigasyon özelliklerine sahip tüm navigasyon özellikleri ile ağır olduğunda. Daha çok var sql = "SİZİN SİZİN NEREDEN SİLİN YOUR_FIELD = @your_parameter" kullanmak istiyorum; this.your_context.Database.ExecuteSqlCommand (sql, yeni SqlParameter ("@ parametreniz", parametreniz));
curiousBoy

2

Daha genel yaklaşım

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

Entity Framework 6 ile kullanabilirsiniz Remove. Ayrıca usingbağlantınızın kapalı olduğundan emin olmak için kullanmak iyi bir taktiktir .

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

1

Sadece ileri geri zıpladığım üç yönteme katkıda bulunmak istedim.

Yöntem 1:

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

Yöntem 2:

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

Yöntem 2 ile gitmeyi tercih etmemin nedenlerinden biri, EF veya EFCore ayarında QueryTrackingBehavior.NoTrackingdaha güvenli olması.

Sonra Yöntem 3 var:

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

Bu, kaydın DeletedOnözelliğini ayarlayarak ve kaydı ne olursa olsun gelecekte kullanmak için yumuşak bir silme yaklaşımı kullanır . Temel olarak, Geri Dönüşüm Kutusu'na koymak .


Ayrıca, tüm kaydı değiştirilecek şekilde ayarlamak yerine Yöntem 3 ile ilgili olarak :

entry.State = EntityState.Modified;

Ayrıca yalnızca sütunu DeletedOndeğiştirilmiş olarak ayarlamanız gerekir :

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

Bunun hakkında ne düşünüyorsunuz, basit ya da değil, bunu da deneyebilirsiniz:

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

0

Genel DAO için benim çalışma finnaly bu:

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


0

basitçe böyle yapabilirsin

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

model

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

} 

onu arayacağınız görünümü

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

umarım bunu anlamanız kolay olur


0

Izgaradaki tıklama veya celldoubleclick etkinliğinizde böyle bir şey yapabilirsiniz (eğer kullandıysanız)

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

Ardından Sil Düğmenizde böyle bir şey yapın:

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
}

Alternatif olarak, LINQ To Entities Sorgusu kullanmak yerine bir LINQ Sorgusu kullanabilirsiniz:

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

employed.Id , DataGridView cihazınızın CellDoubleClick Olayından daha önce iletilmiş olan filtreleme parametresi olarak kullanılır.


Kodun arkasındaki fikir, silmek istediğiniz kaydın kimliğini (employed.Id) modele (Çalışan Sınıfı) bağlar ve ardından Bağlamdan gerçek Tabloya iliştirir ve ardından bellek içi Remove () Yöntemini çalıştırır. son olarak SaveChanges () yöntemini kullanarak veritabanına gerçek kaydetme işlemini gerçekleştirin. Gerçi LINQ Sorgusu da iyi çalışıyor ama sadece kayıt id almak için tablo sorgulama fikrini sevmiyorum.
arvin aquio

0

İşte güvenli bir yol:

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

Burada istediğiniz tüm değişiklikleri biriktirebilirsiniz, böylece SaveChanges ve Command işlemlerinden önce bir dizi silme işlemi yapabilirsiniz, böylece yalnızca hepsi başarılıysa uygulanır.


0

En iyi yol kontrol edip silmektir

        if (ctx.Employ.Any(r=>r.Id == entity.Id))
        {
            Employ rec = new Employ() { Id = entity.Id };
            ctx.Entry(rec).State = EntityState.Deleted;
            ctx.SaveChanges();
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.