Objek tidak dapat dihapus karena tidak ditemukan di ObjectStateManager

114

Saya mendapatkan pesan kesalahan ini "Objek tidak dapat dihapus karena tidak ditemukan di ObjectStateManager."

Kode saya adalah:

    protected MyEntities sqlEntities;

    public virtual void Delete(TEntity entity)
    {
        System.Type t = typeof(TEntity);
        sqlEntities.DeleteObject(entity);
        sqlEntities.SaveChanges();
    }
Sami
sumber
5
Maaf, ada masalah dalam kode yang menggunakan objek konteks data yang berbeda untuk mengambil dan menghapus rekaman.
Sami
Saya mengalami bug seperti ini: var entity = new TEntity() { PK_ID = 23 }; sqlEntities.DeleteObject(entity);Saya mencoba membuat entitas tiruan dengan PK-nya yang disetel dengan benar, dengan harapan Kerangka Kerja Entitas akan memanggil DeleteObject berdasarkan PK
C. Tewalt

Jawaban:

156

Itu berarti bahwa entitas tidak dilampirkan (tidak dimuat oleh contoh konteks yang sama). Coba ini:

protected MyEntities sqlEntities;

public virtual void Delete(TEntity entity)
{
    sqlEntities.Attach(entity);
    sqlEntities.DeleteObject(entity);
    sqlEntities.SaveChanges();
}
Ladislav Mrnka
sumber
1
Terima kasih Ladislav. Ini membantu saya ketika saya memiliki dua konteks saat menghapus data anak dari orang tua - yang dipanggil dari konteks berbeda, di luar TransactionScope. Memindahkan panggilan orang tua di dalam ruang lingkup dan konteks yang sama dan masalah saya terpecahkan.
dan richards
1
@ Ladislav: Jika saya menggunakan .Attach, saya mendapatkan kesalahan yang berbeda: "Objek entitas tidak dapat direferensikan oleh beberapa contoh IEntityChangeTracker." Apakah ini berarti bahwa sudah ada contoh objek lain yang hidup mencegah penghapusan?
Matt
2
@Matt: Tidak, itu berarti objek Anda sudah dilampirkan ke konteks lain. Itu tidak bisa dilampirkan ke dua pada waktu yang sama. Anda harus menggunakan konteks asli untuk menghapus entitas.
Ladislav Mrnka
@ Ladislav: Terima kasih, itu membantu saya melihat lebih jauh - Saya menemukan pertanyaan ini yang sepertinya menjawab bagaimana mengatasinya: Apakah mungkin untuk memeriksa apakah suatu objek sudah dilampirkan ke konteks data di Entity Framework? . Anda benar, tampaknya inilah masalah dalam kasus saya. Terima kasih atas jawaban cepatnya!
Matt
Terima kasih atas pengingatnya, saya telah melampirkannya saat memperbarui rekaman, tetapi tidak saat saya menghapus rekaman.
pinmonkeyiii
60

Hanya klarifikasi kecil atas jawaban Ladislav Mrnka (yang seharusnya merupakan jawaban yang diterima).

Jika seperti saya, Anda punya kode dalam format seperti ini:

using (var context = new MyDataContext())
{
    context.MyTableEntity.Remove(EntytyToRemove);
    var nrOfObjectsChanged = context.SaveChanges();
}

..lalu inilah yang ingin Anda lakukan:

using (var context = new MyDataContext())
{
    // Note: Attatch to the entity:
    context.MyTableEntity.Attach(EntityToRemove);

    context.MyTableEntity.Remove(EntityToRemove);
    var nrOfObjectsChanged = context.SaveChanges();
}

Mungkin ini tampak jelas, tetapi pada awalnya tidak jelas bagi saya bahwa perlu menentukan entitas yang akan dicocokkan, dan bukan hanya konteksnya .

Kjartan
sumber
1
Saya menggunakan pendekatan ini dan menerima pengecualian: "Menyimpan pembaruan, menyisipkan, atau menghapus pernyataan mempengaruhi jumlah baris yang tidak terduga (0). Entitas mungkin telah dimodifikasi atau dihapus sejak entitas dimuat. Segarkan entri ObjectStateManager."
kat1330
11

Sekedar menyesuaikan penjelasan Kjartan:

Saya punya:

public Project DeleteProject(int id)
    {
        using (var context = new Context())
        {
            var p = GetProject(id);
            context.Projects.Remove(p);
            context.SaveChanges();
            return p;
        }
    }

Masalahnya adalah saya menggunakan metode saya sendiri (GetProject ()) untuk mendapatkan entitas (karenanya menggunakan konteks lain untuk memuat entitas):

public Project GetProject(int id)
    {
        using (var context = new Context())
        {
            var project = context.Projects
                .Include(p => p.Reports.Select(q => q.Issues.Select(r => r.Profession)))
                .Include(p => p.Reports.Select(q => q.Issues.Select(r => r.Room)))
                .SingleOrDefault(x => x.Id == id);
            return project;      
        }
    }

Salah satu solusinya adalah dengan melampirkan entitas yang dimuat seperti yang dinyatakan Kjartan, solusi lain dapat menjadi solusi tambang, untuk memuat entitas dalam konteks yang sama:

public Project DeleteProject(int id)
    {
        using (var context = new Context())
        {
            var p = context.Projects.SingleOrDefault(x => x.Id == id);
            if (p == null)
                return p;

            context.Projects.Remove(p);
            context.SaveChanges();
            return p;
        }
    }
esbenr
sumber
2

Saya tahu pertanyaan ini cukup lama tetapi tidak ada yang di atas yang berhasil untuk saya karena saya menghapus register dari lebih dari satu kelas / layanan dan masing-masing dari mereka memberi contoh konteks koneksi database itu sendiri.

Apa yang saya lakukan untuk menyelesaikannya adalah mengirim konteks pertama yang dibuat ke kelas / layanan lainnya yang akan mengakses database.

Misalnya, saya serviceAakan menghapus beberapa register dan memanggilnya serviceBdan serviceCmelakukan hal yang sama dengan register mereka.

Saya kemudian akan menghapus register saya serviceAdan meneruskan sebagai parameter konteks yang dibuat pada serviceAke serviceBdan serviceC.

Terkhos
sumber
2

Anda dapat menulis kode ini:

var x=yourquery.FirstOrDefault(); 

sqlEntities.DeleteObject(x);
sqlEntities.SaveChanges();
mehdi
sumber
1

Jika tidak ada yang berhasil, Anda dapat mencoba solusi ini:

context.Entry(yourObject).State = System.Data.Entity.EntityState.Deleted; context.SaveChanges();

Ala 'Alnajjar
sumber
0

Anda harus yakin bahwa objek Anda ada dalam daftar yang Anda coba hapus, Anda harus meletakkan kondisi berikut

if (context.entity.contains (objek Anda))

Singkirkan.

jika Anda memiliki kondisi yang rumit untuk kesetaraan, Anda harus mengganti metode yang sama di kelas entitas untuk menempatkan kondisi Anda untuk kesetaraan, untuk mendapatkan cara yang benar untuk metode ekstensi "entity.contains"

Mohammad Ahmad Abdullah
sumber
0

Pastikan model yang diteruskan ke Remove (Entity) sama persis dengan record database.

Terkadang mungkin untuk meneruskan model tanpa beberapa bidang seperti Id atau Tanggal. simpan itu di @ html.Hiddenfor jika Anda memposting sebagai formulir.

Cara terbaik adalah dengan meneruskan ID dan mendapatkan entitas menggunakan metode Find (Id) dan meneruskannya ke Hapus (Entity)

Semoga ini bisa membantu seseorang.

Dheeraj Palagiri
sumber
0

Saya mendapat masalah ini dan menyelesaikannya. Cukup salin kode di bawah ini:

sqlEntities.Attach(entity);
sqlEntities.Remove(entity);
sqlEntities.SaveChanges();
vahid sabet
sumber
0

Dalam kasus saya, ada satu konteks, tetapi saya mendapatkan entitas dengan opsi 'AsNoTracking'

vborutenko
sumber