Grid'de üçüncü görünen satırı üçüncü kayıt sanmak, sıralama değiştirilene kadar fark edilmeyen bir hatadır. Kullanıcı puana göre sıraladığında, bir filtre eklediğinde veya sonraki sayfaya geçtiğinde ekran sırası değişir; kaydın kimliği değişmez. Not girişi gibi toplu düzenleme ekranlarında bu ayrımı veri sözleşmesinin merkezine koyarım.
Satır numarası görüntüleme bilgisidir
Arşivdeki not giriş ekranlarında listeleme, sıralama ve kaydetme işleyicileri ayrı. Buradaki bağımsız örnekte veritabanı yerine iki kaydı olan bir sözlük kullanıyorum. 205 kimlikli kayıt önce, 101 kimlikli kayıt sonra güncelleniyor. .NET 10 konsol projesinde çalıştırıldığında sonuç yine kimliklere göre hesaplanır.
var stored = new Dictionary<int, decimal?> { [101] = null, [205] = 40m };
var edits = new[] { (Id:205, Score:(decimal?)70m), (Id:101, Score:(decimal?)0m) };
foreach (var edit in edits)
{
if (!stored.ContainsKey(edit.Id)) throw new ArgumentException("Unknown record");
if (edit.Score is < 0 or > 100) throw new ArgumentException("Out of range");
}
foreach (var edit in edits) stored[edit.Id] = edit.Score;
Console.WriteLine($"101={stored[101]};205={stored[205]}");
stored[205] değerinin 70, stored[101] değerinin 0 olması istek sırasından bağımsızdır. Aynı yaklaşım WebForms GridView içinde DataKeyNames ve DataKeys ile kurulabilir: Id görünür hücre metninden veya satır indeksinden çıkarılmaz. Ancak tarayıcının gönderdiği kimlik hâlâ doğrulanması gereken girdidir. Gizli bir alan olması ona güvenlik özelliği kazandırmaz.
İki geçişin sağladığı ve sağlamadığı
İlk foreach bütün gönderimi denetler. Bilinmeyen bir kimlik ya da aralık dışı puan varsa hiçbir sözlük ataması yapılmadan hata oluşur. İkinci foreach ancak bu ön koşul tamamlanınca değişiklikleri uygular. Böylece iki kayıttan ilki doğru, ikincisi yanlış olduğunda bellekte yarım bir değişiklik bırakmamış oluruz.
Bu, veritabanı transaction'ı değildir. Gerçek kayıtta bağlantı hatası, kısıt ihlali veya başka bir kullanıcının güncellemesi iki yazmanın arasına girebilir. Servis düzeyinde bütün düzenleme kümesinin kapsamını doğrular, transaction içinde yazar ve eşzamanlılık beklentisini ayrıca kontrol ederim. Ön kontrol ile commit arasında değişmeyecekmiş gibi davranmam.
Null ile sıfırı karıştırmamak
decimal? kullanımı bilinçli: null henüz not girilmediğini, 0 ise girilmiş sıfır puanı temsil edebilir. Formdaki boş metni otomatik sıfıra çevirmek bu farkı siler. Örneğin koşulu null değeri aralık dışında saymaz. İş kuralı “bütün satırlar tamamlanmalı” diyorsa ayrıca null kontrolü gerekir; C# nullable karşılaştırmasının bu kararı bizim yerimize vermesini beklemem.
Gönderimde aynı Id iki kez bulunursa örnekte ikinci atama kazanır. Kullanıcının niyeti belirsizleştiği için gerçek bir toplu düzenleme isteğinde mükerrer kimliği baştan reddetmeyi tercih ederim. Sütun adlarını da açık tutarım: CurrentScore, ProposedScore ve varsa ExpectedVersion farklı sorumluluklar taşır.
Var olan kayıt, düzenlenebilir kayıt olmayabilir
Sunucuda yalnız ContainsKey benzeri bir varlık kontrolü yetmez. Kayıt doğru dönem, ekran kapsamı ve kullanıcı yetkisi içinde olmalı. İstemci tüm Id değerlerini bildiğinde bile yalnız yetkili olduğu satırları değiştirebilmelidir. Toplu istekte kimlikleri tek seferde yetkili sorgudan okuyup eksik kalanları bulmak, her satıra ayrı sorgu göndermekten daha düzenli bir akış sağlar.
Bu ekran uzun süre açık kalabiliyorsa sürüm numarası da taşırım. A kullanıcısı 40 puanı görürken B bunu 60 yapmışsa A'nın eski formundan gelen 70 değerinin sessizce kazanması istenmeyebilir. 409 benzeri bir çakışma yanıtı, düzenlenen değerleri kaybetmeden kullanıcıya güncel kaydı inceleme imkânı verir.
Arayüzde başarı ne zaman gösterilmeli?
Seçim kutusu veya yerel model değiştiğinde kalıcı kayıt tamamlanmış olmaz. Kayıt butonu istek sürerken çift gönderimi engellemeli; sunucu hatasında düzenlemeler korunmalı. Testi ters sırada kimlikler, geçerli sıfır, null, 101 puan, mükerrer kimlik ve yetkisiz kayıtla genişletirim. Başarılı senaryoda ekrandan çıkıp yeniden açınca da aynı değerleri okumak isterim.