Pertanyaan Kerangka Entitas 5 Memperbarui Rekaman


Saya telah menjelajahi berbagai metode pengeditan / pembaruan catatan dalam Entity Framework 5 dalam lingkungan ASP.NET MVC3, tetapi sejauh ini tidak satupun dari mereka mencentang semua kotak yang saya butuhkan. Saya akan menjelaskan mengapa.

Saya telah menemukan tiga metode yang akan saya sebutkan pro dan kontra:

Metode 1 - Muat rekaman asli, perbarui setiap properti

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    original.BusinessEntityId = updatedUser.BusinessEntityId;
    original.Email = updatedUser.Email;
    original.EmployeeId = updatedUser.EmployeeId;
    original.Forename = updatedUser.Forename;
    original.Surname = updatedUser.Surname;
    original.Telephone = updatedUser.Telephone;
    original.Title = updatedUser.Title;
    original.Fax = updatedUser.Fax;
    original.ASPNetUserId = updatedUser.ASPNetUserId;
    db.SaveChanges();
}    

Pro

  • Dapat menentukan properti mana yang berubah
  • Tampilan tidak perlu berisi semua properti

Cons

  • 2 x query pada database untuk memuat asli kemudian perbarui

Metode 2 - Muat rekaman asli, setel nilai yang diubah

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    db.Entry(original).CurrentValues.SetValues(updatedUser);
    db.SaveChanges();
}

Pro

  • Hanya properti yang dimodifikasi yang dikirim ke basis data

Cons

  • Tampilan harus berisi setiap properti
  • 2 x query pada database untuk memuat asli kemudian perbarui

Metode 3 - Melampirkan catatan yang diperbarui dan atur status ke EntityState.Modified

db.Users.Attach(updatedUser);
db.Entry(updatedUser).State = EntityState.Modified;
db.SaveChanges();

Pro

  • 1 x kueri di basis data untuk diperbarui

Cons

  • Tidak dapat menentukan properti mana yang berubah
  • Tampilan harus berisi semua properti

Pertanyaan

Pertanyaan saya untuk kalian; apakah ada cara yang bersih agar saya dapat mencapai serangkaian tujuan ini?

  • Dapat menentukan properti mana yang berubah
  • Tampilan tidak perlu berisi semua properti (seperti kata sandi!)
  • 1 x kueri di basis data untuk diperbarui

Saya mengerti ini adalah hal yang sangat kecil untuk menunjukkan tetapi saya mungkin kehilangan solusi sederhana untuk ini. Jika tidak metode yang akan menang ;-)


811
2018-03-11 10:27


asal


Jawaban:


Anda mencari:

db.Users.Attach(updatedUser);
var entry = db.Entry(updatedUser);
entry.Property(e => e.Email).IsModified = true;
// other changed properties
db.SaveChanges();

645
2018-03-11 13:12



Saya sangat suka jawaban yang diterima. Saya percaya ada cara lain untuk mendekati ini juga. Katakanlah Anda memiliki daftar properti yang sangat pendek yang tidak ingin Anda sertakan dalam Tampilan, jadi ketika memperbarui entitas, itu akan dihilangkan. Katakanlah kedua bidang tersebut adalah Kata Sandi dan SSN.

db.Users.Attach(updatedUser);

var entry = db.Entry(updatedUser);
entry.State = EntityState.Modified;

entry.Property(e => e.Password).IsModified = false;
entry.Property(e => e.SSN).IsModified = false;   

db.SaveChanges();   

Contoh ini memungkinkan Anda pada dasarnya meninggalkan logika bisnis Anda sendiri setelah menambahkan bidang baru ke tabel Pengguna Anda dan ke Tampilan Anda.


168
2017-08-01 21:01



foreach(PropertyInfo propertyInfo in original.GetType().GetProperties()) {
    if (propertyInfo.GetValue(updatedUser, null) == null)
        propertyInfo.SetValue(updatedUser, propertyInfo.GetValue(original, null), null);
}
db.Entry(original).CurrentValues.SetValues(updatedUser);
db.SaveChanges();

27
2017-11-12 11:33



Saya telah menambahkan metode pembaruan tambahan ke kelas basis repositori saya yang mirip dengan metode pembaruan yang dibuat oleh Scaffolding. Alih-alih mengatur seluruh objek untuk "diubah", itu menetapkan satu set sifat individu. (T adalah parameter generik kelas.)

public void Update(T obj, params Expression<Func<T, object>>[] propertiesToUpdate)
{
    Context.Set<T>().Attach(obj);

    foreach (var p in propertiesToUpdate)
    {
        Context.Entry(obj).Property(p).IsModified = true;
    }
}

Dan kemudian memanggil, misalnya:

public void UpdatePasswordAndEmail(long userId, string password, string email)
{
    var user = new User {UserId = userId, Password = password, Email = email};

    Update(user, u => u.Password, u => u.Email);

    Save();
}

Saya suka satu perjalanan ke database. Mungkin lebih baik untuk melakukan ini dengan model tampilan, meskipun, untuk menghindari mengulang set properti. Saya belum melakukannya karena saya tidak tahu bagaimana menghindari membawa pesan validasi pada validator model tampilan saya ke dalam proyek domain saya.


21
2018-04-25 16:19



public interface IRepository
{
    void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class;
}

public class Repository : DbContext, IRepository
{
    public void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class
    {
        Set<T>().Attach(obj);
        propertiesToUpdate.ToList().ForEach(p => Entry(obj).Property(p).IsModified = true);
        SaveChanges();
    }
}

7
2018-03-16 16:04



Hanya untuk menambah daftar opsi. Anda juga dapat mengambil objek dari database, dan menggunakan alat pemetaan otomatis seperti Pemeta Otomatis  untuk memperbarui bagian-bagian dari catatan yang ingin Anda ubah ..


2
2017-12-03 15:58



Bergantung pada kasus penggunaan Anda, semua solusi di atas berlaku. Ini adalah bagaimana saya biasanya melakukannya:

Untuk kode sisi server (misalnya proses batch) saya biasanya memuat entitas dan bekerja dengan proksi dinamis. Biasanya dalam proses batch Anda perlu memuat data lagian pada saat layanan berjalan. Saya mencoba untuk mengambil data secara batch daripada menggunakan metode find untuk menghemat waktu. Tergantung pada proses saya menggunakan kontrol konkurensi yang optimis atau pesimis (saya selalu menggunakan optimis kecuali untuk skenario eksekusi paralel di mana saya perlu mengunci beberapa catatan dengan pernyataan sql biasa, ini jarang terjadi). Tergantung pada kode dan skenario, dampaknya dapat dikurangi hingga hampir nol.

Untuk skenario sisi klien, Anda memiliki beberapa opsi

  1. Gunakan model tampilan. Model harus memiliki UpdateStatus properti (tidak dimodifikasi-dimasukkan-diperbarui-dihapus). Ini adalah tanggung jawab klien untuk mengatur nilai yang benar ke kolom ini tergantung pada tindakan pengguna (insert-update-delete). Server dapat meminta db untuk nilai asli atau klien harus mengirim nilai asli ke server bersama dengan baris yang diubah. Server harus melampirkan nilai asli dan menggunakan kolom UpdateStatus untuk setiap baris untuk memutuskan bagaimana menangani nilai-nilai baru. Dalam skenario ini saya selalu menggunakan konkurensi yang optimis. Ini hanya akan melakukan insert - update - delete statements dan tidak ada pilihan, tetapi mungkin memerlukan beberapa kode pintar untuk berjalan grafik dan memperbarui entitas (tergantung pada skenario - aplikasi Anda). Mapper dapat membantu tetapi tidak menangani logika CRUD

  2. Gunakan pustaka seperti angin.js yang menyembunyikan sebagian besar kerumitan ini (seperti yang dijelaskan dalam 1) dan coba sesuaikan dengan kasus penggunaan Anda.

Semoga itu membantu


1
2018-05-30 12:07