Memakai Entity Framework Di Visual Studio 2010


Dahulu kala, para programmer senang menulis ke database secara langsung melalui SQL, kapanpun dan dimanapun. Tidak lama kemudian, beberapa dari mereka merasakan ‘hukuman’ atas wewenang SQL yang disalahgunakan. Ibarat pemerintah yang mengelola negara selama sepuluh tahun tanpa aturan, visi dan misi yang jelas, beberapa dari programmer ini mulai pusing melihat kode programnya sendiri di saat tugas mereka kian berat. Apakah pada akhirnya para programmer menjadi punah? Tidak! Trend object oriented programming (OOP) kemudian booming dan banyak disebut dimana-mana. Programmer mulai melakukan enkapsulasi kode program pada class. Mereka juga menciptakan aplikasi berlapis (layer), class untuk framework (infrastruktur), dan sebagainya. Teknik OOP yang digunakan secara benar membuat para programmer menjadi disiplin. Mereka mendidik diri sendiri untuk mematuhi aturan yang mereka (atau tim mereka) buat. Walaupun mereka kehilangan keleluasaan untuk bertindak sesuka hati, pada akhirnya kode program mereka menjadi rapi dan memiliki pola yang dapat ditelusuri secara mudah. OOP ibarat polisi yang tidak segan memberi hukuman bila ada yang melanggar aturan.

Salah satu ciri penerapan OOP adalah adanya kumpulan class yang disebut sebagai domain class yang mewakili permasalahan bisnis yang sedang dihadapi. Sesungguhnya apa yang sering diberikan sebagai contoh pada mata kuliah atau buku OOP seperti Kucing, Tikus, Motor, dan Pesawat adalah bagian dari domain class. Mereka juga kerap disebut sebagai entity class. Istilah entity disini mirip seperti pada Entity-relationship model (ER model) yang dipakai untuk mendeskripsikan isi database.

Sebuah domain class atau entity class saja tidak cukup untuk membuat sebuah aplikasi. Masih banyak hal lain dalam sebuah aplikasi seperti presentation (layar form), penyimpanan data, dan sebagainya. Sebuah entity yang telah diciptakan oleh aplikasi perlu disimpan ke dalam database. Aplikasi juga perlu menampilkan satu atau lebih entity yang tersimpan di dalam database. Agar proses pengambilan dan penyimpanan data berlangsung secara transparan, saya dapat memakai Object-relational Mapping (ORM). Dengan memakai ORM, saya memiliki sebuah lapisan abstraksi dimana saya tidak perlu memberikan perintah SQL secara langsung. Tujuannya adalah agar saya bisa lebih berfokus pada object yang ada (karena ini adalah OOP)!

Selama ini, saya selalu memakai Java Persistence API (JPA) dengan Hibernate sebagai providernya. JPA adalah salah satu bagian dari Java Enterprise Edition (Java EE). Lalu bagaimana dengan C# di .NET Platform? Solusi resmi dari Microsoft adalah Entity Framework (EF). Versi awal dari EF telah disertakan sejak .NET Framework 3.5 Service Pack 1. Versi keduanya mengalami pelonjakan nomor versi yang drastis (dari versi 1 menjadi 4), Entity Framework 4.0 . EF 4.0 adalah bagian dari .NET Framework 4.0.

Bahasa Java berjalan pada Java Platform yang versi terakhirnya adalah Java 7. Tidak berbeda jauh, hasil program yang memakai fasilitas .NET harus dijalankan pada komputer yang memiliki .NET Framework. Apa versi terakhir dari .NET Framework yang ter-install di komputer saya? Untuk menjawab pertanyaan tersebut, saya dapat memberikan perintah seperti yang terlihat seperti pada gambar berikut ini:

Memeriksa versi .NET Framework

Memeriksa versi .NET Framework

Nilai Release berupa 0x5c786 (atau desimal 378758) menunjukkan bahwa saya telah men-install .NET Framework 4.5.1. Perlu diperhatikan bahwa .NET Framework dapat di-download dan di-install secara gratis tanpa pungutan biaya. Tapi saya tidak bisa senang dulu!! Walaupun .NET Framework gratis, Visual Studio adalah produk berbayar. Masalahnya: Setiap rilis Visual Studio dikaitkan dengan .NET Framework versi tertentu! Sebagai contoh, Visual Studio 2005 mendukung .NET 2.0, Visual Studio 2008 mendukung .NET 3.5, Visual Studio 2010 mendukung hingga maksimal .NET 4, dan Visual Studio 2013 yang mendukung .NET 4.5.1. Ini artinya, untuk mengembangkan aplikasi yang memakai .NET 4.5, saya harus memiliki Visual Studio 2012 atau Visual Studio 2013.

Untuk membuktikannya, saya men-klik kanan sebuah proyek dan memilih menu Properties. Kemudian, pada tab Application, di bagian Target Framework, saya hanya akan menemukan maksimal nilai .NET Framework 4 (walaupun saya sudah men-install .NET Framework 4.5.1), seperti yang terlihat pada gambar berikut ini:

Mengubah Target Framework Di Visual Studio 2010

Mengubah Target Framework Di Visual Studio 2010

Versi terbaru dari Entity Framework adalah EF 6.0.1. Lalu, bila saya tetap memakai Visual Studio 2010, apa versi Entity Framework yang dipakai? Visual Studio 2010 dilengkapi dengan EF 4.0 secara bawaan. Jangan tertipu dengan namanya: EF 4.0 adalah versi kedua karena Microsoft langsung loncat 3 angka agar nomor versi EF lebih sinkron dengan versi .NET Framework-nya. Walaupun saya men-download EF 6.0.1, saya tidak akan memperoleh fitur maksimal yang membutuhkan .NET 4.5 karena Visual Studio 2010 hanya mendukung hingga .NET 4. Selain itu, saya juga tidak bisa memperoleh tooling untuk perancangan visual terbaru (minimal harus Visual Studio 2012). Tapi setidaknya mungkin saya bisa memperoleh perbaikan di sisi runtime.

Langkah pertama yang saya lakukan untuk men-upgrade Entity Framework di Visual Studio 2010 adalah men-download NuGet Package Manager di http://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c. NuGet adalah repository (di http://www.nuget.org/packages) semacam Apache Maven di Java. Entity Framework dan Microsoft ASP.NET MVC adalah salah satu contoh proyek yang dapat dipakai melalui NuGet. Setelah proses download selesai, saya men-double click file NuGet.Tools.vsix untuk men-install extension tersebut di Visual Studio 2010. Setelah proses instalasi selesai, bila saya membuka menu Tools, Extension Manager… di Visual Studio, saya akan menemukan sebuah entry bernama NuGet Package Manager.

Langkah berikutnya, saya akan membuat sebuah proyek Console Application untuk Visual C#. Setelah proyek selesai dibuat, bila saya memilih menu Project, saya akan menemukan item menu baru seperti yang terlihat pada gambar berikut ini:

Menu Dari NuGet

Menu Dari NuGet

Saya kemudian memilih menu Manage NuGet Packages… (saya memastikan bahwa komputer telah terhubung ke internet sebelum memilih menu ini). Saya kemudian men-klik menu Online, nuget.org untuk melihat daftar packages yang dapat saya pakai. Saya kemudian mencari Entity Framework dan men-klik tombol Install seperti yang terlihat pada gambar berikut ini:

Men-install Entity Framework Ke Proyek

Men-install Entity Framework Ke Proyek

Setelah proses instalasi selesai, saya kini siap untuk mencoba membuat program yang memakai Entity Framework. Sama seperti pada saat memakai JPA, ada beberapa pendekatan dalam memulai sebuah proyek yang memakai Entity Framework yaitu code first (membuat class terlebih dahulu), database first (membuat tabel di database terlebih dahulu), atau model first (menggambar model di Visual Studio yang kemudian akan menghasilkan database dan class). Selama ini, saya sudah terbiasa membuat kode program sehingga saya akan memakai pendekatan code first.

Saya mulai dengan membuat class ItemPenjualan yang isinya seperti berikut ini:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace LatihanOOP
{
    class ItemPenjualan
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }

        [Required]
        [MinLength(5), MaxLength(100)]
        public string NamaBarang { get; set; }

        public int Jumlah { get; set; }

        public decimal Harga { get; set; }

        public decimal Total()
        {
            return Jumlah * Harga;
        }
    }
}

Berikutnya, saya membuat sebuah class Penjualan yang mengandung (komposisi) satu atau lebih ItemPenjualan seperti yang terlihat pada kode program berikut ini:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace LatihanOOP
{
    class Penjualan
    {        
        public Penjualan()
        {
            DiskonPersen = 0;            
        }

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }

        [MinLength(4), MaxLength(4)]
        public string Nomor { get; set; }

        [Required]
        public DateTime Tanggal { get; set; }

        [Required]
        [MinLength(3), MaxLength(200)]
        public string Konsumen { get; set; }

        public decimal DiskonPersen { get; set; }

        public virtual List<ItemPenjualan> ListItemPenjualan { get; set; }              

        public decimal Total()
        {
            decimal total = ListItemPenjualan.Sum(i => i.Total());
            return total - (DiskonPersen / 100 * total);
        }

        public override string ToString()
        {
            return string.Format("Nomor: {0}, Tanggal: {1}, Konsumen: {2}",
                Nomor, Tanggal.ToString("dd-MM-yyyy"), Konsumen);
        }
    }
}

Pada pendekatan code first, sebuah property di class yang namanya ID atau nama class diikuti dengan ID akan dianggap sebagai primary key. Dengan demikian, pada kode program di atas PenjualanID akan menjadi primary key di tabel yang dihasilkan nanti. Selain itu, property ListItemPenjualan memiliki keyword virtual sehingga dapat di-override untuk mengimplementasikan proxy sehingga menciptakanlazy loading. Dalam kosa kata ORM, lazy loading berarti nilai property ListItemPenjualan tidak di-isi dari database saat sebuah Penjualan di-query. Nilai property tersebut baru akan diambil dari database hanya bila ia dibutuhkan (saat di-akses melalui getter-nya).

Salah satu hal penting yang perlu diperhatikan pada ORM adalah nagivasi. Sebuah entity umumnya dapat melakukan navigasi ke entity lainnya melalui property. Hal ini mirip seperti join antar tabel pada database relasional. Sebagai contoh, sebuah entity Penjualan dapat melakukan navigasi ke entity ItemPenjualan yang dimilikinya melalui property ListItemPenjualan. Akan tetapi hal sebaliknya tidak berlaku: sebuah entity ItemPenjualan tidak dapat melakukan navigasi ke Penjualan yang berhubungan dengannya. Navigasi seperti ini disebut sebagai unidirectional. Bila navigasi berlaku dua arah dimana ItemPenjualan juga dapat mengakses Penjualan, maka ia disebut sebagai bidirectional.

Berikutnya, saya membuat sebuah class yang diturunkan dari DbContext seperti berikut ini:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;

namespace LatihanOOP
{
    class LatihanContext : DbContext
    {
        public LatihanContext() : base("DatabaseLatihan") { }

        public DbSet<Penjualan> DaftarPenjualan { get; set; }

    }
}

Instance dari DbContext ini akan mewakili seluruh operasi yang berkaitan dengan baca tulis object ke database. Pada JPA, class ini setara dengan sebuah persistence context yang diwakili oleh EntityManagerFactory. Pada kode program di atas, saya memanggil superclass dengan nilai constructor "DatabaseLatihan". Dengan demikian, EF akan menggunakan database dengan nama DatabaseLatihan. Lalu bagaimana dengan pengaturan lainnya seperti database apa yang akan dipakai, nama user, password, dan sebagainya? EF akan memakai salah satu database Microsoft SQL Server Express atau LocalDB yang ditemukan. Karena Visual Studio 2010 memiliki database SQL Server 2008 Express secara bawaan, maka database tersebut secara otomatis akan dipakai. Kenapa bukan MySQL atau JavaDB yang otomatis dipakai? Tidak ada yang protes soal monopoli Microsoft lagi?😉

Saya dapat melihat informasi lebih detail dengan membuka file App.config. Pada proyek saya, isi file tersebut terlihat seperti berikut ini:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" ... />
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />    
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

Untuk mengubah database yang dipakai, saya perlu memodifikasi nilai atribut type pada node defaultConnectionFactory. Pada konfigurasi saya, yang dipakai adalah class System.Data.Entity.Infrastructure.SqlConnectionFactory. Class factory ini akan memakai database Microsoft SQL Server dengan nama .\SQLEXPRESS. Bila ingin memakai instance database lain, saya perlu menambahkan node parameters untuk mengisi constructor factory tersebut dengan nama instance SQL Server atau mendeklarasikan connection string secara eksplisit.

Berikutnya, saya akan membuat kode program yang menyimpan beberapa object ke database seperti berikut ini:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LatihanOOP
{
    class Program
    {
        static void Main(string[] args)
        {
            Penjualan p1 = new Penjualan() { Nomor = "F001", Konsumen = "Snake", Tanggal = new DateTime(2014, 1, 1) };
            p1.ListItemPenjualan = new List<ItemPenjualan>()
            {
                new ItemPenjualan() { NamaBarang = "SOCOM Pistol", Jumlah = 1, Harga = 10 },
                new ItemPenjualan() { NamaBarang = "ID Card", Jumlah = 2, Harga = 20 },
                new ItemPenjualan() { NamaBarang = "Optical Disc", Jumlah = 1, Harga = 50 }
            };           

            Penjualan p2 = new Penjualan() { Nomor = "F002", Konsumen = "Liquid Snake", Tanggal = new DateTime(2014, 1, 5) };
            p2.ListItemPenjualan = new List<ItemPenjualan>()
            {
                new ItemPenjualan() { NamaBarang = "Ration", Jumlah = 10, Harga = 5 },
                new ItemPenjualan() { NamaBarang = "Stealth Camouflage", Jumlah = 1, Harga = 300 }
            };
            p2.DiskonPersen = 5;

            Penjualan p3 = new Penjualan() { Nomor = "F003", Konsumen = "Big Boss", Tanggal = new DateTime(2014, 3, 15) };
            p3.ListItemPenjualan = new List<ItemPenjualan>()
            {
                new ItemPenjualan() { NamaBarang = "Thermal Goggles", Jumlah = 1, Harga = 100 },
                new ItemPenjualan() { NamaBarang = "Night Vision Goggles", Jumlah = 1, Harga = 120 },
                new ItemPenjualan() { NamaBarang = "Body Armour", Jumlah = 20, Harga = 10 },
                new ItemPenjualan() { NamaBarang = "Cigarettes", Jumlah = 100, Harga = 2 }
            };
            p3.DiskonPersen = 10.5M;

            Console.WriteLine("Sedang menyimpan object ke database...");

            using (var db = new LatihanContext())
            {
                db.DaftarPenjualan.Add(p1);
                db.DaftarPenjualan.Add(p2);
                db.DaftarPenjualan.Add(p3);
                db.SaveChanges();
            }

            Console.WriteLine("Object berhasil disimpan ke database.");
            Console.ReadKey();
        }
    }
}

Pada saat program di atas dijalankan, Entity Framework akan membuat sebuah database dengan nama DatabaseLatihan (sesuai nilai constructor untuk superclass di LatihanContext). Ia juga akan membuat tabel yang dibutuhkan, seperti yang terlihat pada tampilan Microsoft SQL Server Management Studio seperti pada gambar berikut ini:

Schema yang dihasilkan oleh Entity Framework

Schema yang dihasilkan oleh Entity Framework

Tiga object Penjualan pada program di atas akan tersimpan dalam bentuk record di tabel dan setiap tabel dapat memiliki hubungan dengan tabel lainnya (database relasional) seperti yang terlihat pada gambar berikut ini:

Isi tabel setelah penyimpanan object

Isi tabel setelah penyimpanan object

Sekarang, saya akan mencoba membuat kode program yang mengambil object dari database seperti berikut ini:

using (var db = new LatihanContext())
{
    var hasil = from p in db.DaftarPenjualan
                where p.Tanggal.Month == 1 && p.Tanggal.Year == 2014
                select p
                ;

    Console.WriteLine("Daftar Penjualan Di Bulan Januari 2014:");
    foreach (Penjualan p in hasil)
    {
        Console.WriteLine(p);
    }
}
Console.ReadKey();

Hasil dari kode program di atas adalah:

Daftar Penjualan Di Bulan Januari 2014:
Nomor: F001, Tanggal: 01-01-2014, Konsumen: Snake
Nomor: F002, Tanggal: 05-01-2014, Konsumen: Liquid Snake

Pada kode program di atas, saya memakai LINQ untuk mencari seluruh object Penjualan di bulan Januari 2014. Sangat sederhana bukan? Tapi seorang paranoid akan berkata: “LINQ memang indah, tapi jelas ia tidak dapat menggantikan SQL!” Oleh sebab itu, Entity Framework juga tetap memberikan kesempatan untuk menggunakan perintah SQL. Sebagai contoh, kode program berikut ini memiliki hasil yang sama seperti sebelumnya, tetapi tidak memakai LINQ melainkan SQL:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LatihanOOP
{
    class Program
    {
        static void Main(string[] args)
        {

            using (var db = new LatihanContext())
            {

                var hasil = db.DaftarPenjualan.SqlQuery(
                    "SELECT * FROM Penjualans WHERE MONTH(Tanggal) = 1 AND YEAR(Tanggal) = 2014");

                Console.WriteLine("Daftar Penjualan Di Bulan Januari 2014:");
                foreach (Penjualan p in hasil)
                {
                    Console.WriteLine(p);
                }

            }

            Console.ReadKey();
        }
    }
}

Perihal Solid Snake
I'm nothing...

2 Responses to Memakai Entity Framework Di Visual Studio 2010

  1. Ping-balik: Memakai Entity Framework Dengan Pendekatan Database First | The Solid Snake

  2. Ping-balik: Menerapkan MVVM Di Windows Presentation Foundation (WPF) | The Solid Snake

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: