Soran
Linq Mssql server deki cascade silme işlemi

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.
- Değiştirilmiş Tür Kyamuran SalibryamMicrosoft contingent staff, Moderator 7 Kasım 2016 Pazartesi 14:25
Tüm Yanıtlar
-
-
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);
- Düzenleyen CetinBasozEditor 2 Kasım 2016 Çarşamba 15:03
-
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.
-
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.
-
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).
- Düzenleyen carg2626 2 Kasım 2016 Çarşamba 21:33 edit
-
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?