Konsep yang akan saya tuliskan ini bukan murni konsep dari saya sendiri, namun rangkuman dari beberapa tulisan-tulisan dari para penulis yang lebih ahli di ASP.NET, MSDN dan StackOverflow, yang kesemuanya berbahasa Inggris (maaf, lupa mencatat sumber-sumbernya). Tulisan ini adalah rangkuman dan sebagian terjemahan dari tulisan aslinya, untuk membantu sesama programmer pemula yang belum terlalu fasih berbahasa Inggris, khususnya teman-teman di likungan kerja dan daerah saya. Semoga bermanfaat.
Menyimpan Rekam Jejak Perubahan Data
Pada project-project sebelumnya, untuk menyimpan rekam jejak perubahan data, saya melakukannya dengan menambahkan beberapa baris kode pada setiap Action yang melakukan operasi perubahan pada data.
Public Class BukuController Inherits Controller Private db As New MyWebAppEntities 'tidak ada perubahan data pada action ini... Function Index() As ActionResult Return View() End Function 'belum ada perubahan data... Function Add() As ActionResult Return View() End Function 'terjadi perubahan data: INSERT <HttpPost> <ValidateAntiForgeryToken> Function Add(<Bind(Include:="Judul,PengarangId,JenisId,Keterangan")> buku As TabelBuku) As ActionResult If ModelState.IsValid Then db.TabelBuku.Add(buku) Dim log As New TabelLog log.NamaTabel = "Buku" log.Tipe = "INSERT" log.DirubahOleh = User.Identity.Name log.DirubahPada = Now log.DataLama = "" log.DataBaru = JsonConvert.SerializeObject(buku, MyJsonSerializerSetting) db.TabelLog.Add(log) db.SaveChanges() Return RedirectToAction("Index") End If Return View(buku) End Function 'belum ada perubahan data... Function Edit(id As Integer?) As ActionResult If IsNothing(id) Then Return RedirectToAction("Index") Dim buku As TabelBuku = db.TabelBuku.Find(id) If IsNothing(buku) Then Return View("NotFound") Return View(buku) End Function 'terjadi perubahan data: UPDATE <HttpPost> <ValidateAntiForgeryToken> Function Edit(<Bind(Include:="Id,Judul,PengarangId,JenisId,Keterangan")> buku As TabelBuku) As ActionResult If ModelState.IsValid Then db.Entry(buku).State = Entity.EntityState.Modified Dim log As New TabelLog log.NamaTable = "Buku" log.Tipe = "UPDATE" log.DirubahOleh = User.Identity.Name log.DirubahPada = Now log.DataLama = JsonConvert.SerializeObject(db.Entry(buku).GetDatabaseValues, MyJsonSerializerSetting) log.DataBaru = JsonConvert.SerializeObject(db.Entry(buku).CurrentValues, MyJsonSerializerSetting) db.TabelLog.Add(log) db.SaveChanges() Return RedirectToAction("Index") End If Return View(buku) End Function 'belum ada perubahan data... Function Delete(id As Integer?) As ActionResult If IsNothing(id) Then Return RedirectToAction("Index") Dim buku As TabelBuku = db.TabelBuku.Find(id) If IsNothing(buku) Then Return View("NotFound") Return View(buku) End Function 'terjadi perubahan data: DELETE <HttpPost> <ActionName("Delete")> <ValidateAntiForgeryToken> Function DeleteConfirmed(id As Integer) As ActionResult Dim buku As TabelBuku = db.TabelBuku.Find(id) Dim log As New TabelLog log.NamaTable = "Buku" log.Tipe = "DELETE" log.DirubahOleh = User.Identity.Name log.DirubahPada = Now log.DataLama = JsonConvert.SerializeObject(buku, MyJsonSerializerSetting) log.DataBaru = "" db.TabelLog.Add(log) db.TabelBuku.Remove(buku) db.SaveChanges() Return View("Index") End Function End ClassMetode ini membuat saya harus menulis beberapa baris kode pada setiap Action dari Controller yang melakukan operasi perubahan data, satu per satu secara manual. Anda bisa bayangkan, bila aplikasi web yang sedang dibangun terdiri dari banyak Controller dan lebih banyak lagi Action. Ini menjadi sangat melelahkan dan tidak efektif.
Override fungsi SaveChanges() pada Entity
Operasi perubahan data (penyimpanan data) yang sebenarnya terjadi pada fungsi SaveChanges() dari entity. Kita dapat melakukan override terhadap fungsi ini dan memasukkan beberapa baris kode untuk menyimpan rekam jejak perubahan data yang kita inginkan. Berikut adalah contoh final code yang saya gunakan, sebagai bahan referensi.
Partial Class MyWebAppEntities Public Overrides Function SaveChanges() As Integer 'periksa apakah ada perubahan data. bila ada, lanjutkan... If Me.ChangeTracker.HasChanges Then 'daftar nama tabel yang TIDAK akan direkam perubahannya Dim excludeName() As String = {"TabelLog","TabelAktifitas","TabelLainnya"} Dim aTime As DateTime = Now Dim aUser As String = "" Dim ipAddr As String = "" 'entity ini kita gunakan pada aplikasi web, maka HttpContext.Current pasti selalu ada If Not IsNothing(HttpContext.Current) Then aUser = HttpContext.Current.User.Identity.Name ipAddr = HttpContext.Current.Request.UserHostAddress End If 'periksa setiap entry yang berstatus Added, Deleted dan Modified pada entity For Each e As Entity.Infrastructure.DbEntityEntry In Me.ChangeTracker.Entries.Where(Function(f) f.State = Entity.EntityState.Added Or f.State = Entity.EntityState.Deleted Or f.State = Entity.EntityState.Modified) 'lanjutkan bila nama tabel dari entry ini (e.Entity.GetType.Name) tidak ada dalam daftar excludeName (yang TIDAK direkam perubahannya) If Not excludeName.Contains(e.Entity.GetType.Name) Then 'membuat log baru... Dim log As New TabelLog With log .NamaTabel = e.Entity.GetType.Name .DirubahOleh = aUser .DirubahPada = aTime .IpAddress = ipAddr .DataLama = "" .DataBaru = "" End With 'periksa status perubahan data, lakukan perekaman yang sesuai... Select Case e.State Case Entity.EntityState.Added log.Tipe = "INSERT" log.DataBaru = JsonConvert.SerializeObject(e.CurrentValues, MyJsonSerializerSetting) Case Entity.EntityState.Modified log.Tipe = "UPDATE" log.DataLama = JsonConvert.SerializeObject(e.GetDatabaseValues, MyJsonSerializerSetting) log.DataBaru = JsonConvert.SerializeObject(e.CurrentValues, MyJsonSerializerSetting) Case Entity.EntityState.Deleted log.Tipe = "DELETE" log.DataLama = JsonConvert.SerializeObject(e.GetDatabaseValues, MyJsonSerializerSetting) End Select Me.TabelLog.Add(log) End If Next End If 'rutin penyimpanan data yang sebenarnya Return MyBase.SaveChanges() End Function End ClassDengan meng-override fungsi SaveChanges() seperti di atas, kita memeriksa perubahan data terlebih dahulu, lalu membuat rekaman perubahannya dan memasukkannya dalam entity agar ikut tersimpan kemudian. Perhatikan bahwa ada perbedaan sumber data yang direkam antara EntityState.Added, EntityState.Modified dan EntityState.Deleted. Perbedaan utama, sangat tampak khususnya pada EntityState.Modified, bahwa sumber data untuk log.DataLama diambil dari:
e.GetDatabaseValuessedangkan sumber data untuk log.DataBaru diambil dari:
e.CurrentValues
Tantangan selanjutnya dalam menyimpan rekam jejak perubahan data ini adalah memilih metode yang digunakan untuk melakukan serialisasi data. Pada contoh di atas, saya menggunakan Json.NET dari Newtonsoft yang secara built-in telah ada pada Visual Studio 2013 untuk menyimpan data dalam format JSON. Perlu dicatat bahwa fungsi:
Newtonsoft.Json.JsonConvert(Object)akan melakukan serialisasi object secara recursive (object di dalam object pun akan ikut proses serialisasi). Menggunakan fungsi ini pada ADO.NET Entity membuat JsonConvert(object) ikut melakukan serialisasi pada object terkait lain yang memiliki relasi database terhadap object utama. Ini mungkin bisa diterima, bergantung kepada situasi dimana Anda membutuhkannya. Namun untuk project ini, berhubung saya hanya membutuhkan serialisasi object tanpa mengikutkan object lain di dalamnya (yang terkait melalui relasi database), saya menggunakan fungsi:
Newtonsoft.Json.JsonConvert(Object, JsonSerializerSettings)dimana pada Module lain saya membuat JsonSerializerSettings dengan menggunakan ContractResolver khusus untuk tidak mengikutkan property bertipe object pada proses serialisasi. Topik ini akan saya coba perdalam dalam tulisan berikutnya.
Saran, usul, pendapat dan/atau rekomendasi lainnya akan sangat membantu.
vpn_movies/vpn_movies/vpn_movies/movies/vpn_movies/pokflix.svg
BalasHapusvpn_movies/vpn_movies/vpn_movies/mpmp4_movies/vpn_movies/vpn_movies/pokflix.svg. youtube to mp3\