Post Page Advertisement [Top]

         Merhaba,
         Fluent Migrator .Net için veritabanı migrasyon framework' üdür. Bu şu demek oluyor veritabanımız için oluşturmak istediğimiz şemayı, tabloları, foreign key ilişkilerini vb. , kodlayarak oluşturabileceğimiz bir ortam sunuyor. Böylece veritabanımızı oluştururken tüm aşamaları kaydedebiliriz, bir versiyon kontrol sistemine dahil edebiliriz.



Bir çok geliştiricnin aynı zamanda veri tabanı tasarımı üzerinde çalışmasını sağlayarak scriptlerimizin kaybolmasını ya da manuel olarak scriptleri run edilmesini engellemiş oluruz.

Okurken ne dinlemeli ?


       Gelelim .Net Core ile fluent migrator' u nasıl kullanacağımıza bunun için iki adet nuget paketine ihtiyacımız olacak.

  • FluentMigrator.Runner
  • FluentMigrator
     Bir .Net Core Console Application yaratacağımız için Dependeny Injection referanslarımız olmayacak işte bunu için de SturctureMap' dan faydalanacağız. 
  • StructureMap
  • StructureMap.Microsoft.DependencyInjection

        Böylece .Net Console Application'da Dependency Injection'dan faydalanmış olacağız. İlk olarak framework servislerini Microsoft.Extensions.DependencyInjection altında olan ServiceCollection 'a ekliyoruz. Biz burada Fluent Migration kullanacağımız için  AddFluentMigratorCore() 'u ekliyoruz. Konfigurasyonu da bu aşamada yapabiliriz. Connection string'i MySQL mi SQL mi kullanacağımızı, Migration Sınıfmızı bu aşamada belirtiyoruz. Program.cs'nin Main metodunun son hali aşağıdaki gibi olmalı.

static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            // add the framework services
            var services = new ServiceCollection()
                .AddFluentMigratorCore()
                // Configure the runner
                .ConfigureRunner(
                builder => builder
                // Use SQL
                .AddSqlServer2012()
                // The SQL connection string
                .WithGlobalConnectionString("Server=.;Database=JokerGames;Trusted_Connection=True;MultipleActiveResultSets=true")
                // Specify the assembly with the migrations
                .WithMigrationsIn(typeof(InitialMigration).Assembly))
                .BuildServiceProvider();
Şimdi StructureMap'den faydalanarak eklediğimiz servisleri Container'e register edeceğiz.

            var container = new Container();
            container.Configure(config =>
            {
                // Register stuff in container, using the StructureMap APIs...
                config.Scan(_ =>
                {
                    _.AssemblyContainingType(typeof(Program));
                    _.WithDefaultConventions();
                    _.AssemblyContainingType<IMigrationRunnerBuilder>();
                });

            });
Böylece Dependency Injection'umuzu tamamlayıp bu scope' da migration' ları çalıştırabiliriz. Table , foreign key vb. scriptleri oluşturmak için MigrateUp() tabloları silmek vb. için ise RollbackToVersion(0) kullanılmalı.

            try
            {
                using (var scope = services.CreateScope())
                {
                    // Instantiate the runner
                    var runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();

                    // Execute the migrations
                    runner.MigrateUp();

                    //Execute the down scripts
                    //runner.RollbackToVersion(0);

                    Console.WriteLine("Migration has successfully executed.");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
Gelelim migration scriptlerini oluşturacağımız uygulamamıza Joker Games: Online bir oyun  mağazası düşünün. Kullanıcılar oyun satın alabilirler bunun için bir kredi kartı kullanırlar. Her kart yalnızca bir oyuncu ile ilişkilidir. Bir oyuncunun birden çok kartı olabilir. Alımlar oyuncular ve kartlar ile ilişkilidir.
Bu senaryo için up ve down scriptlerimizi yazalım:

    public class InitialMigration : Migration
    {
        public override void Up()
        {
            #region Tables

            Create.Table("Players")
                .WithColumn("Id").AsInt32().NotNullable().PrimaryKey().Identity()
                .WithColumn("Username").AsString(50).NotNullable();

            Create.Table("Cards")
                .WithColumn("Id").AsInt32().NotNullable().PrimaryKey().Identity()
                .WithColumn("Number").AsString(100).NotNullable()
                .WithColumn("PlayerId").AsInt32().Nullable();

            Create.Table("Purchases")
                .WithColumn("Id").AsInt32().NotNullable().PrimaryKey().Identity()
                .WithColumn("Amount").AsDecimal(9, 2).NotNullable()
                .WithColumn("CardId").AsInt32().NotNullable()
                .WithColumn("PlayerId").AsInt32().NotNullable();
            #endregion

            #region Foreign Keys
            Create.ForeignKey("FK_Cards_PlayerId")
                .FromTable("Cards").ForeignColumn("PlayerId")
                .ToTable("Players").PrimaryColumn("Id");

            Create.ForeignKey("FK_Purchases_CardId")
                .FromTable("Purchases").ForeignColumn("CardId")
                .ToTable("Cards").PrimaryColumn("Id");

            Create.ForeignKey("FK_Purchases_PlayerId")
                .FromTable("Purchases").ForeignColumn("PlayerId")
                .ToTable("Players").PrimaryColumn("Id");
            #endregion

       Up metodunu incelediğimizde Players, Cards ve Purchases adında üç tablo oluşturduğumuzu görüyoruz. Players tablosu hiç bir tablo ile bağlı olmadığından bir FK(Forign Key)' i yok. Card tablosu Players tablosu ile birebir ilişkili olduğu için Card tablosunda PlayerId alanı var ve Foreign Keys alanında FK_Cards_PlayerId adında Card tablosunda (From table) PlayerId' ye denk gelen Player tablsunda(To Table) ise Id' ye denk gelen bir FK oluşturuyoruz.

       Alımlar(Purchases) tablosu ise hem Cards hem de Players tablosu ile birebir ilişkili kolonlara sahip. Yukarıdakine benzer şekilde tablo kolonları ve FK' lar oluşturuyoruz. 

       Down metodumuzda ilk olarak FK' leri silip daha sonra tabloları siliyoruz.

        public override void Down()
        {
            #region Foreign Keys

            Delete.ForeignKey("FK_Cards_PlayerId").OnTable("Cards");

            Delete.ForeignKey("FK_Purchases_CardId").OnTable("Purchases");
            Delete.ForeignKey("FK_Purchases_PlayerId").OnTable("Purchases");

            #endregion

            #region Tables
            Delete.Table("Players");
            Delete.Table("Cards");
            Delete.Table("Purchases");
            #endregion

        }

           Burada önemli olan bir nokta da  Migration class'ımızın attributesi : Bu attribute'de versiyon bilgisi ve açıklama alanı bulunur. 


              [Migration(20190418205440, "v1.0.0")]


Biz migration'ı çalıştırdığımızda oluşturduğumuz tablolara ek olarak VersionInfo adında da bir tablo oluşur işte bu tablo migrationlar'ın hafızasıdır aslında. 


Versiyon farklılığı ile migrationlar run edilir. Description'da da yaptığımız işleme dair bilgi eklemiş oluruz. Yaptığımız her yeni değişiklikte versiyon numarasını artırmalıyız. Belirli bir versiyona dönmek istediğimizde  RollbackToVersion(versiyon_no) metodunu kullanabiliriz.

Eğer tablolarımıza ilk datayı insert etmek istiyorsak Up metodunu aşağıdaki gibi kodlayabiliriz.

            #region Initial Data

            Insert.IntoTable("Players")
                .Row(new { Id = 1, Username = "Player1" })
                .Row(new { Id = 2, Username = "Playe2" });
            #endregion

Böylece Fluent Migrator kullanarak projemiz için gerekli olan veri tabanını oluşturmuş olduk. Bir sonraki yazımızda NHibernate kullanrak .Net Core ile Joker Games web uygulmasını yazarak tasarladığımız veritabanını kullanacağız.

Uygulamanın kodlarını burada bulabilirsiniz.

Hoşça kalın,
Multu kalın.

2 yorum:

Bottom Ad [Post Page]