1. Anasayfa
  2. C#

Database Connection Factory Design Pattern in C#

Connection Factory Design Pattern


3

Merhaba bu makalemde herhangi bir database’den bağımsız tüm database tipleri için ortak kullanılabilen IDbConnection tipinde bir connection’ı kullandığımız database’e göre nasıl üretebiliriz onu anlatmak istiyorum.

Öncelikle bunun için bir factory interface’e ihtiyacımız var.

public interface IConnectionFactory : IDisposable
{
    IDbConnection Connection { get; }
}

Burada bu interface’den türetilecek class’ların bize bir IDbConnection dönmesini zorunlu kılıyoruz ve oluşacak class’ımızda Dispose() methodu da zorunlu olacak.

Şimdi yine database’den bağımsız database bilgisi verildiğinde bize bir IDbConnection dönebilen bir factory base yaratalım. Ama bu class’ımız öyle bir class olsun ki Connection yaratsın fakat bu connection’ın hangi database’e ait olduğu bilgisi alt class’lar tarafından verilsin. Burada database bilgisini getiren bir method yapıp bu method’u soyutlaştırmalıyız.

public abstract class ConnectionFactoryBase : IConnectionFactory
    {
        private string connectionString;

        private bool disposedValue = false; // To detect redundant calls

        protected ConnectionFactoryBase(string connectionString)
        {
            this.connectionString = connectionString;
        }

        public IDbConnection Connection
        {
            get
            {
                var factory = this.GetProviderFactory();

                var connection = factory.CreateConnection();
                if (connection == null)
                {
                    throw new Exception("There is available connection factory!");
                }

                connection.ConnectionString = this.GetConnectionString();
                if (connection.State == ConnectionState.Closed)
                {
                    connection.Open();
                }

                return connection;
            }
        }

        public void Dispose()
        {
            // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
            this.Dispose(true);

            // GC.SuppressFinalize(this);
        }

        protected abstract DbProviderFactory GetProviderFactory();

        protected virtual string GetConnectionString()
        {
            return this.connectionString;
        }

        protected virtual void Dispose(bool disposing)
        {
            if (this.disposedValue)
            {
                return;
            }

            if (disposing)
            {
                this.Connection.Close();
            }

            this.disposedValue = true;
        }

        // ~ConnectionFactory() {
        //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        //   Dispose(false);
        // }

        // This code added to correctly implement the disposable pattern.
    }

 

Burada kullandığımız

protected abstract DbProviderFactory GetProviderFactory();

methodu’ı bir abstract method’dur ve hangi provider’ın çağırılacağı alt class’lara bırakılmıştır.

Örneğin buradaki base class’ı kullanarak postgresql için bir connection class’ı tasarlamak istediğimizde yapacağımız işlem şu şekildedir.

public class PostgreConnectionFactory : ConnectionFactoryBase
    {
        public PostgreConnectionFactory(string connectionString)
            : base(connectionString)
        {
        }

        protected override DbProviderFactory GetProviderFactory()
        {
            var factory = DbProviderFactories.GetDbProviderFactory(DataAccessProviderTypes.PostgreSql);
            return factory;
        }
    }

Sadece abstract olarak tasarlanan GetProviderFactory method’umuzun içerisini postgresql’e göre tasarlayarak sorunumuzu çözmüş olduk.

Şimdi tek eksiğimiz;

DbProviderFactories.GetDbProviderFactory(DataAccessProviderTypes.PostgreSql); yapısının nasıl çalıştığını anlamak kaldı.

public enum DataAccessProviderTypes
    {
        SqlServer,
        SqLite,
        MySql,
        PostgreSql,
    }

    public class DbProviderFactories
    {
        public static DbProviderFactory GetDbProviderFactory(DataAccessProviderTypes type)
        {
            switch (type)
            {
                case DataAccessProviderTypes.SqlServer:
                    return SqlClientFactory.Instance;
                case DataAccessProviderTypes.SqLite:
                    return GetDbProviderFactory("Microsoft.Data.Sqlite.SqliteFactory", "Microsoft.Data.Sqlite");
                case DataAccessProviderTypes.MySql:
                    return GetDbProviderFactory("MySql.Data.MySqlClient.MySqlClientFactory", "MySql.Data");
                case DataAccessProviderTypes.PostgreSql:
                    return GetDbProviderFactory("Npgsql.NpgsqlFactory", "Npgsql");
                default:
                    throw new NotSupportedException("Unsupported_Provider");
            }
        }

        public static DbProviderFactory GetDbProviderFactory(string providerName)
        {
            var providername = providerName.ToLower();

            if (providerName == "system.data.sqlclient")
            {
                return GetDbProviderFactory(DataAccessProviderTypes.SqlServer);
            }

            if (providerName == "system.data.sqlite" || providerName == "microsoft.data.sqlite")
            {
                return GetDbProviderFactory(DataAccessProviderTypes.SqLite);
            }

            if (providerName == "mysql.data.mysqlclient" || providername == "mysql.data")
            {
                return GetDbProviderFactory(DataAccessProviderTypes.MySql);
            }

            if (providerName == "npgsql")
            {
                return GetDbProviderFactory(DataAccessProviderTypes.PostgreSql);
            }

            throw new NotSupportedException(string.Format("Unsupported_Provider", providerName));
        }

        private static DbProviderFactory GetDbProviderFactory(string dbProviderFactoryTypeName, string assemblyName)
        {
            var instance = ReflectionUtils.GetStaticProperty(dbProviderFactoryTypeName, "Instance");
            if (instance == null)
            {
                var a = ReflectionUtils.LoadAssembly(assemblyName);
                if (a != null)
                {
                    instance = ReflectionUtils.GetStaticProperty(dbProviderFactoryTypeName, "Instance");
                }
            }

            if (instance == null)
            {
                throw new InvalidOperationException(string.Format("UnableToRetrieveDbProviderFactoryForm", dbProviderFactoryTypeName));
            }

            return instance as DbProviderFactory;
        }
    }

Burada assembly üzerinden Type bilgisi gönderilen database provider’ını dönen bir provider factory yazmış olduk burada da.

Artık Connection Factory yapımız hazır. Bir sonra ki makalemde görüşmek üzere.

Hoşçakalın.

 

Bu konuyla ilgili sorularınızı  alt kısımda bulunan yorumlar alanını kullanarak sorabilirsiniz.

Referanslar

www.mshowto.org

TAGs : C# SQL, Design Patterns, factory method tasarim deseni

Bu İçeriğe Tepkin Ne Oldu?
  • 10
    harika_
    Harika!!
  • 0
    be_enmedim
    Beğenmedim
  • 0
    _ok_iyi
    Çok iyi
  • 0
    sevdim_
    Sevdim!
  • 0
    bilemedim_
    Bilemedim!
  • 0
    olmad_
    Olmadı!
  • 0
    k_zd_m_
    Kızdım!

Fatih Mert, lisans eğitimini Sakarya Üniversite Bilgisayar Mühendisliği’nde tamamlamıştır. Şu anda Bahçeşehir Üniversitesi’nde Yapay Zeka yüksek lisansı okumaktadır. İş hayatında üniversitenin ilk yıllarında .Net ve Sql Server gibi Microsoft teknolojileri ile başlamış ve sonrasında Xamarin, Azure, Angular ve Flutter gibi teknoljilerle de ilgilenip çeşitli yazılımlar üretmiştir. Arçelik, Doğuş Yayın Grubu, Aygaz, Doğan Medya gibi sektörün önde gelen firmalarında C#, .Net, Sql Server, Xamarin ürünleri ile çalışmış, Design Patterns ve Enterprise Architecture konularıyla uzun süredir uğraşmaktadır. Şu anda Xinerji Software firmasında Yazılım Mimarı ve Ekip Lideri olarak çalışmaktadır.

Yazarın Profili
İlginizi Çekebilir

Bültenimize Katılın

Tıklayın, üyemiz olun ve yeni güncellemelerden haberdar olan ilk kişi siz olun.

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Yorumlar (3)

  1. 18/03/2021

    Beynine sağlık Fatih, çok iyi.

  2. Tebrikler. Eline emeğine sağlık harika bir paylaşım olmuş.

  3. 20/03/2021

    Junior seviyesindeki meslektaşlarımız için muazzam bir makale olmuş. Fatih gibi insanlar bu ülke için değer, umarım kıymetleri bilinir. Çünkü bildiğini paylaşma fırsatı olacak kadar zaman maliyeti yapabilen yazılımcı bir elin parmağını geçmeyecek kadar az.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir