23 Temmuz 2015 Perşembe

Unique olmayan kayıtları topluca silmek (bulk delete non-unique records)

Merhaba arkadaşlar,

Bu yazımda, tabloda Unique olmayan kayıtları toplu olarak silmeyi ele alacağım. Üzerinde çalışacağımız senaryoda, kayıtları daha önce gelişigüzel girilmiş, AirPortCode ve AirPortName adında alanları bulunan bir tablom var. AirPortCode alanı unique olması icab eden bir alan ancak tablo bu şekilde yapılandırılmamış ve bir çok mükerrer kayıt girişi yapılmış. Şu durumda Management Studio(SSMS) ortamında AirportCode alanını primary key yapmak istediğimde SSMS aşağıdaki hatayı dönmekte;

 'AirPorts' table
- Unable to create index 'PK_AirPorts'.
The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name 'dbo.AirPorts' and the index name 'PK_AirPorts'. The duplicate key value is (BAY).
Could not create constraint. See previous errors.
The statement has been terminated.


Yani alanın primary key olmasına engel teşkil eden mükerrer ilk kaydı gösterip işlemi yapamadığını söylüyor.

zahmetli de olsa, her bir hata için mükerrer tablo kayıtlarını edit modda açıp silmek istediğimde ise;

---------------------------
Microsoft SQL Server Management Studio
---------------------------
No rows were deleted.

A problem occurred attempting to delete row 1.
Error Source: Microsoft.SqlServer.Management.DataTools.
Error Message: The row value(s) updated or deleted either do not make the row unique or they alter multiple rows(2 rows).

Correct the errors and attempt to delete the row again or press ESC to cancel the change(s).
---------------------------
OK   Help  
---------------------------


silmek istenen kayıttan birebir aynı birden fazla kayıt olduğundan işlemi bu yöntemle de gerçekleştiremiyoruz.


--mükerrer haavalanlarını ve adetlerini tutacağımız değişkenlerimizi tanımlıyoruz.
declare @AirPortCode varchar(3), @AirPortCount int
--mükerrer kayıt kalmayana kadar döngü çalışacak. işlemi cursor kullanarak ta yapabilirsiniz.
while exists(select null from AirPorts group by AirPortCode having COUNT(AirPortCode)>1)
begin
/*mükerrer havaalanı ve ilgili havaalanının mükerrer kayıt sayısı bulunuyor.
kayıt sayısının 1 eksigini alarak tabloda tek kayıt kalmasını sağlamış oluyoruz.
*/

select @AirPortCode = AirPortCode, @AirPortCount = COUNT(AirPortCode) - 1
from AirPorts group by AirPortCode having COUNT(AirPortCode)>1
--bulunan değer kadar kaydı siliyoruz
delete top (@AirPortCount) from AirPorts where AirPortCode = @AirPortCode
end;


artık AirportCode alanını primary key olarak atayabiliriz. Tablo ve data scriptini buradan indirebilirsiniz.

faydalı olması dileğimle,

bir sonraki yazımda görüşmek üzere,
Yaşar Şahin






14 Temmuz 2015 Salı

Sınıf ve Üyelere Açıklama Eklemek

Merhaba arkadaşlar,

özellikle üçüncü parti dll kütüphanerinde kullandığımız fonsiyonların işlevlerini bilmek işimizi kolaylaştırmaktadır. Bu yazıda kendi oluşturacağımız sınıf ve üyelerine açıklama ekleyeceğiz.

Basitçe oluşturulmuş bir toplama fonksiyonu aşağıdaki gibi iken;

public static class Hesaplamalar
    {
        public static double Topla(double p1, double p2)
        {
            return p1 + p2;
        }
    }


 Hesaplamalar statik sınıfı altındaki static Topla fonksiyonunu çağırmak istediğimde intellisense varsayılan açıklaması aşağıdaki resimdeki gibi olmaktadır.

Sınıf ve sınıf üyeleri tanımlalarının hemen üst satırına /// işareti eklediğimizde editör ilgili açıklama şablonunu oluşturmaktadır.Metod açıklamalarına her bir parametre için ayrı ayrı açıklama girilebilmektedir.

    /// <summary>
    /// Hesaplamalar sınıfı
    /// </summary>

    public static class Hesaplamalar
    {
        /// <summary>
        /// parametresine girilen değerleri toplar.
        /// </summary>
        /// <param name="p1">double türünden değerler virgül ile ayrılarak, ya da double bir dizi parametre olarak geçilebilir</param>
        /// <returns>double değer döndürür</returns>

        public static double Topla(params double[] p1)
        {
            return p1.Sum();
        }
    }

editörde metodu kullanmak istediğimizde intellisense açıklamayı getirecektir;


kütüphanenizdeki sınıf ve üyerine açıklamalar girerek hem kendinizin hem de paylaştığınız kullanıcıların sınıf ve üyelerinin amaçlarını hatırlamasını/anlamasını kolaylaştırmış olacaksınız.

Bir sonraki yazımda görüşmek üzere,
Yaşar Şahin


8 Temmuz 2015 Çarşamba

TurboTimer (kalıtımla sınıf genişletme)

Merhaba arkadaşlar,

dün bir blogda, timer komponentinin kullanımında, kod içinde timer çalışma durumunun tespiti için, başka bir nesnenin isminin değiştirilerek kullanıldığını gördüm. Kodu aynen almıyorum ancak temel olarak yapılan şuydu;

if (this.Text == "timer is running")
            {
                timer1.Stop();
                this.Text = "timer stopped";
            }
            else
            {
                timer1.Start();
                this.Text = "timer is running";
            }

böyle bir çözüm üretilmesinin sebebi timer nesnesinin çalışma durumunu gösteren belirgin bir property(özellik) olmaması olmalı diye düşünüp, biraz da can sıkıntısından timer'a bir kıyak geçeyim dedim ve timer sınıfından türettiğim TurboTimer sınıfıyla, timera hem bir özellik ekledim hem de çalışma durumu değişikliklerine abonelik yapılsın deyip bir de event handler(olay tutucu) tanımladım. bakın nasıl yapmışım;

//timerstate numaralandırıcısı ile artık intellisense hizmetimizde olacak.
    public enum TimerState { running, stopped }

    public class TurboTimer: System.Windows.Forms.Timer//temel sınıf adına dikkat çünkü frameworkte birden çok timer sınıfı var.
    {
        //özelliğimin varsayılan değerini atıyorum.
        private TimerState currentState = TimerState.stopped;
        public TimerState CurrentState { get { return currentState; } set { currentState = value; } }
        //özellik durum değişikliklerini izlemek isteyen metodlara tutucu tanımlıyorum.        public event EventHandler<TimerStateChangeEventArgs> TimerStateChanged;
        //özelliğimi temel sınıfın enabled özelliğine göre set ediyorum. burada temel sınıfın Enabled özelliğini ezmemiz gerekti.         public override bool Enabled
        {
            get
            {
                return base.Enabled;
            }
            set
            {
                base.Enabled = value;
                this.CurrentState = (base.Enabled) == true ? TimerState.running : TimerState.stopped;
                /*durum değişikliği oluştuğunda abonelere (subscriber) haber vereceğimiz metodu çağırıyorum.
                 * bu sayede aboneler, kendi abonelik metodlarından durumu değerlendirebilecekler.
                 * TimerStateChangeEventArgs sınıfı ile, aboneye, sınıfım içinden istediğim bilgileri gönderiyorum.
                 */
                OnTimerStateChanged(new TimerStateChangeEventArgs(this.CurrentState));
            }
        }
        //öncelikle abonem var mı diye bakıyorum ki işlemci karavana çalışmasın :)        protected virtual void OnTimerStateChanged(TimerStateChangeEventArgs timerStateChangeEventArgs)
        {
            EventHandler<TimerStateChangeEventArgs> handler = TimerStateChanged;
            if (handler != null)
            {
                handler(this, timerStateChangeEventArgs);
            }
        }
    }
    //aboneye göndermek istediğim bilgileri (olay argümanları), EventArgs sınıfından türetilmiş sınıfta belirtiyorum,
    //yukarıda da tetiklemeden önce doldurmuştuk.
    public class TimerStateChangeEventArgs : EventArgs
    {
        public TimerState CurrentState { get; set; }
        public TimerStateChangeEventArgs(TimerState pState)
        {
            this.CurrentState = pState;
        }
    }

TurboTimer sınıfımız Timer komponentinden ve dolayısıyla Component sınıfından türediğinden, kodu derlediğinizde, Tollboxta TurboTimer komponentini göreceksiniz.

 


böylece sınıfımızı toolboxtan sürükleyerek te kullanabileceğiz. 
Esas olarak burada yapılan, bir sınıfa kalıtım yolu ile ek işlevsellikler kazandırmaktır. Yukarıdaki kodları ve, komponenti kullandığım örnek Windows uygulamasını buradan indirebilirsiniz.

Bir sonraki yazımda görüşmek üzere,
Yaşar Şahin