none
Linq Mssql server deki cascade silme işlemi RRS feed

  • Genel Tartışma

  • Merhabalar

    Mvc ile geliştirmekte olduğum bir uygulamada ilişkili tablolarım mevcut.

    Gelirlerim > Taksitler ve AlinanStoklar tablosuyla ,

    Taksitlerim Tahsilatlar tablosuyla ilişkili

    Kullanıcım yanlış düzenlenen bir geliri silmek istediğinde ben arka planda ilgili kaydın görünürlük durumunu false yapıyorum.yani veritabanından sildirmiyorum. Bu işlemin sağlıklı olabilmesi için Gelirler tablosunun ilişkili olduğu diğer tablolarda (Taksitler , AlinanStoklar,Tahsilatlar ) görünürlüklerini false yapmalıyım.

    Kod tarafında

    var k = db.TBL_GIDERLER.FirstOrDefault(C =>C.ID == id);
    k.AKTIF = false;
    db.SaveChanges();

    diyerek işlemimi halledebiliyorum.

    Ancak ilişkili her tablo için uzun uzun for döngüleri yazmam gerekiyor. Bunun gibi:

                foreach (var item in k.ALINANSTOKLAR)
                {
                    item.AKTIF = false;
                }
                foreach (var item in k.TAKSITLER)
                {
                    item.AKTIF = false;
                }
                foreach (var item in k.TAKSITLER.Select(C=>C.TAHSILATLAR))
                {
                    foreach (var it in item)
                    {
                        it.AKTIF = false;
                    }
                }
    db.SaveChanges();

    Yeni bir ilişkili tablo eklemem gerektiğinde yine buraya geri dönüp yeni eklediğim tablo için de bir for döngüsü oluşturmam gerekiyor. Bu işlem bana pek programatik gelmiyor.Benim şunu demem lazım: Gelirler tablomda silme işlemi yapıyorsam ilişkili tablolarda da silme işlemini yap.(tabi bu silme sql server tarafındaki delete rule = cascade işleminden biraz farklı olması gerekiyor.)

    Sizler bu tarz verilerin silinmemesi gerektiği seneryolarda neler yapıyorsunuz?

    Önerilerinizi ve benim seneryomdaki çözümlerinizi bekliyorum.Şimdiden çok teşekkür ederim.

    2 Kasım 2016 Çarşamba 13:20

Tüm Yanıtlar

  • Neden Stored Procedure kullanmıyorsunuz? id'yi gönderip tüm tabloları stored procedure içinde update ederseniz. Bir başka yöntem ise trigger kullanmak ama bu yöntemi çok sevmiyorum.

    http://pgnchess.com
    http://dergikapaklari.com

    2 Kasım 2016 Çarşamba 13:33
  • Database seviyesinde yapmak istiyorsaniz, trigger kullanin. En pratigi bu, kod tarafinda degisiklik gerekmez.

    Kod tarafinda kullanmak istiyorsaniz, dongu yazmanin zahmetinden cok bunun veritabanina N tane komut olarak gitmesi problem. Onun yerine db.DataBase.ExecuteSqlCommand[Async]() kullanabilirsiniz. Ornek:

    var k = db.TBL_GIDERLER.FirstOrDefault(C => C.ID == id);
    k.AKTIF = false;
    db.SaveChanges();
    
    db.Database.ExecuteSqlCommand("Update ALINANSTOKLAR set Aktif=0 where GiderlerId = @p0", id);
    db.Database.ExecuteSqlCommand("Update TAKSITLER set Aktif=0 where GiderlerId = @p0", id);
    db.Database.ExecuteSqlCommand(@"Update TAHSILATLAR set Aktif=0 where exists 
    (select * from Taksitler 
      where Taksitler.GiderId = @p0 and Taksitler.Id = Tahsilatlar.TaksitId)", id);


    2 Kasım 2016 Çarşamba 15:02
    Yanıtlayıcı
  • Neden ilişkili her tabloda Aktif diye bir kolon var ?

    Mesela demişsiniz ki var item in k.ALINANSTOKLAR

    Buradan anladığımız her bir ALINANSTOK kaydının GELIR ile bir ilişkisi var. Bu ilişki üzerinden gitmeniz daha mantıklı olacak bence.

    Biraz daha açmak gerekirse şöyle,

    Siz bir geliri iptal etmek istediğinizde sadece aşağıdaki işlemi yapacaksınız.

    var gelir = dbContext.Gelirler.Find(gelirId);
    gelir.Aktif = false;
    dbContext.SaveChanges();

    Bu gelire bağlı diğer tablolardaki kayıtları kullanacağınız zamanda, navigation property ile gidip gelirin aktif olup olmadığına bakacaksınız, Yani şöyle;

    int gelirId = 15; //gelir id'niz
    DateTime baslangic = DateTime.Parse("01.10.2016");
    DateTime bitis = DateTime.Parse("31.10.2016").AddDays(1);
    
    var buAykiTaksitler = dbContext.Taksitler.Where(p=>p.Tarih >= baslangic && p.Tarih < bitis && p.Gelir.Aktif == true).ToList();
    

    Yani burada aslında koddan çok mantığınızda sıkıntı var bence.


    oguzkurtcuoglu.com


    2 Kasım 2016 Çarşamba 15:05
  • Neden ilişkili her tabloda Aktif diye bir kolon var ?

    Mesela demişsiniz ki var item in k.ALINANSTOKLAR

    Buradan anladığımız her bir ALINANSTOK kaydının GELIR ile bir ilişkisi var. Bu ilişki üzerinden gitmeniz daha mantıklı olacak bence.

    Biraz daha açmak gerekirse şöyle,

    Siz bir geliri iptal etmek istediğinizde sadece aşağıdaki işlemi yapacaksınız.

    var gelir = dbContext.Gelirler.Find(gelirId);
    gelir.Aktif = false;
    dbContext.SaveChanges();

    Bu gelire bağlı diğer tablolardaki kayıtları kullanacağınız zamanda, navigation property ile gidip gelirin aktif olup olmadığına bakacaksınız, Yani şöyle;

    int gelirId = 15; //gelir id'niz
    DateTime baslangic = DateTime.Parse("01.10.2016");
    DateTime bitis = DateTime.Parse("31.10.2016").AddDays(1);
    
    var buAykiTaksitler = dbContext.Taksitler.Where(p=>p.Tarih >= baslangic && p.Tarih < bitis && p.Gelir.Aktif == true).ToList();

    Yani burada aslında koddan çok mantığınızda sıkıntı var bence.


    oguzkurtcuoglu.com


    Ben de ilk once ayni seyi dusundum de, sanirim gider tablosundan bagimsiz olarak herhangibir ALINANSTOK satirini da AKTIF false yapmak istiyor (yani bir cesit tablo basina "deleted" isareti). 
    2 Kasım 2016 Çarşamba 15:10
    Yanıtlayıcı
  • Ben de ilk once ayni seyi dusundum de, sanirim gider tablosundan bagimsiz olarak herhangibir ALINANSTOK satirini da AKTIF false yapmak istiyor (yani bir cesit tablo basina "deleted" isareti). 

    Evet haklısınız çetin hocam bende tam bunu yazmak üzereydim.ALINANSTOKLAR neyse de tahsilatları ve taksitleri de silmek gerekebiliyor.
    • Düzenleyen carg2626 2 Kasım 2016 Çarşamba 21:33 edit
    2 Kasım 2016 Çarşamba 21:26
  • Yorumlarınız için teşekkürler. Sp ile yada çetin hocamın dediği gibi yapmak daha mantıklı sanırım.Bu işlemi yapmamın amacı eğer bi silme işlemi yapılıyorsa bunu hangi kullanıcı hangi tarih saatte hangi nedenle yapıyor.bu gibi verileri kaydettiriyorum.kötü niyetli bir personel bütün verileri silebilir. kim olduğu belli olsun diye.hepsini geçtim verilerin güvende kalması da ayrı bir neden. Peki bu gibi durumlarda sizler neler yapıyorsunuz fikirlerinizi alabilirmiyim?
    2 Kasım 2016 Çarşamba 21:31