Saturday, November 11, 2017

FluentGenerator kullanarak Oracle Entity Framework 6.x sınıflarının oluşturulması - Generating Oracle Entity Framework classes with FluentGenerator

FluentGenerator (FG) Entity Framework 6.x (EF) code first örüntüsüne göre sınıfların oluşturulması için yazılmış bir masaüstü uygulamasıdır. Oluşturulan sınıflar "fluent" mimariye göre oluşturulur ve POCO ve bağlantı (mapping) sınıfları ayrı ayrı oluşturulur.

FG, ProjectBase (PB) kütüphanesini kullandığı için uygulamanın çalıştırılması için PB' nin eklenmesi ve provider ayarlamalarının yapılması gerekir. Eğer Oracle unmanaged provider kullanılıyorsa "Oracle Client" kurulmalı ve ilgili ayarlamalar yapılmalıdır.

FG ve PB'yi aşağıdaki adresten indirebilirsiniz:

https://github.com/vyigity

Test veri tabanı olarak Oracle 11g express edition ve HR şeması içinde yer alan ögeler kullanılacaktır.



FG çalıştırıldığında config ayarlamalarına göre bağlantı cümleciği arayüzde görünecektir. Cümlecik değiştirilmek istenirse istenen yeni cümlecik girilir ve "CHANGE" tuşu ile yeni cümlecik geçerli hale getirilir. Namespace ismini kendi projenize göre belirledikten sonra "DIR" tuşu ile EF sınıflarının hangi klasör içinde oluşturulacağı seçilmelidir. Capitalization kısmında sınıf isimlerinin nasıl formatlanacağı seçilebilmektedir. Bu örnekte "Pascal" kullanılacaktır. Üstte yer alan TABLE_NAME kısmında tablo ismine göre, alttaki VIEW_NAME kısmından view ismine göre arama yapılabilir.

Örnek olarak görselde de görüleceği üzere "Employees" tablosuna ilişkin sınıfları oluşturmak istiyoruz. Arama kısmına "EMPL" yazarak istediğimiz tabloya ulaştık ve yön tuşları ile tabloyu sağ tarafta yer alan grid içine alarak bu tablonun oluşturulacağını belirttik. Son olarak "GENERATE" tuşu nu kullandığımızda önceden seçtiğimiz klasör içinde sınıflar aşağıdaki gibi oluşturulacaktır:

.\Generate\Context.cs

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using YourNameSpace.Models.Mapping;

namespace YourNameSpace.Models
{
    public partial class DatabaseContext : DbContext
    {
        static DatabaseContext()
        {
            Database.SetInitializer<DatabaseContext>(null);
        }

        public DatabaseContext()
            : base("Name=Context")
        {
        }

        public DbSet<Employees> Employeess { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new EmployeesMap());
        }
    }
}

Context sınıfı EF'nin temel sınıfıdır ve FG foreign key (FK) ilişkileri oluşturmadığı için bu konuyla ilgili kodlar elden bu sınıf içine eklenmelidir. Map sınıfları "OnModelCreating" fonksiyonu içine yukarıdaki gibi eklenmeli ve DbSet tanımlaması sonraki eklentiler için elden yapılmalıdır.

.\Generate\Employees.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace YourNameSpace.Models
{
    public partial class Employees
    {
        public int EmployeeId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string PhoneNumber { get; set; }
        public DateTime HireDate { get; set; }
        public string JobId { get; set; }
        public Nullable<decimal> Salary { get; set; }
        public Nullable<decimal> CommissionPct { get; set; }
        public Nullable<int> ManagerId { get; set; }
        public Nullable<short> DepartmentId { get; set; }

    }
}

Yukarıda EF Employees POCO sınıfının nasıl göründüğü verilmiştir.

.\Generate\Mapping\EmployeesMap.cs

using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;

namespace YourNameSpace.Models.Mapping
{
    public class EmployeesMap : EntityTypeConfiguration<Employees>
    {
        public EmployeesMap()
        {
            // Primary Key
            this.HasKey(t => new { t.EmployeeId });

            // Properties
            this.Property(t => t.EmployeeId)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

            this.Property(t => t.FirstName)
                .HasMaxLength(20);

            this.Property(t => t.LastName)
                .IsRequired()
                .HasMaxLength(25);

            this.Property(t => t.Email)
                .IsRequired()
                .HasMaxLength(25);

            this.Property(t => t.PhoneNumber)
                .HasMaxLength(20);

            this.Property(t => t.JobId)
                .IsRequired()
                .HasMaxLength(10);

            // Table & Column Mappings
            this.ToTable("EMPLOYEES", "HR");
            this.Property(t => t.EmployeeId).HasColumnName("EMPLOYEE_ID");
            this.Property(t => t.FirstName).HasColumnName("FIRST_NAME");
            this.Property(t => t.LastName).HasColumnName("LAST_NAME");
            this.Property(t => t.Email).HasColumnName("EMAIL");
            this.Property(t => t.PhoneNumber).HasColumnName("PHONE_NUMBER");
            this.Property(t => t.HireDate).HasColumnName("HIRE_DATE");
            this.Property(t => t.JobId).HasColumnName("JOB_ID");
            this.Property(t => t.Salary).HasColumnName("SALARY");
            this.Property(t => t.CommissionPct).HasColumnName("COMMISSION_PCT");
            this.Property(t => t.ManagerId).HasColumnName("MANAGER_ID");
            this.Property(t => t.DepartmentId).HasColumnName("DEPARTMENT_ID");
        }
    }
}

EmployeesMap sınıfı EF haritalama ve bazı validation kodlarını içeren sınıftır. Validation kodlarının burada bulunması zorunlu değildir. İstenmesi durumunda etiket (Attribute) usulü de uygulanabilir. Bütün sınıfları projenize eklediğinizde EF ile ilgili veri tabanı nesneleri üzerinde işlem yapmaya başlayabilirsiniz.