Öğretici: CRUD İşlevselliği Uygulama - ile MVC ASP.NET EF Core
Önceki öğreticide Entity Framework ve SQL Server LocalDB kullanarak verileri depolayan ve görüntüleyen bir MVC uygulaması oluşturdunuz. Bu öğreticide, MVC iskelesinin denetleyicilerde ve görünümlerde sizin için otomatik olarak oluşturduğu CRUD (oluşturma, okuma, güncelleştirme, silme) kodunu gözden geçirecek ve özelleştireceksiniz.
Dekont
Denetleyicinizle veri erişim katmanı arasında bir soyutlama katmanı oluşturmak için depo düzenini uygulamak yaygın bir uygulamadır. Bu öğreticileri basit tutmak ve Entity Framework'ün kendisini kullanmayı öğretmeye odaklanmak için depoları kullanmaz. EF ile depolar hakkında bilgi için bu serideki son öğreticiye bakın.
Bu öğreticide şunları yaptınız:
- Ayrıntılar sayfasını özelleştirme
- Oluştur sayfasını güncelleştirme
- Düzenle sayfasını güncelleştirme
- Sil sayfasını güncelleştirme
- Veritabanı bağlantılarını kapatma
Ön koşullar
Ayrıntılar sayfasını özelleştirme
Öğrenci Dizini sayfasının iskelesi oluşturulmuş kodu özelliğin dışında Enrollments
bıraktı, çünkü bu özellik bir koleksiyon barındırıyor. Ayrıntılar sayfasında, koleksiyonun içeriğini bir HTML tablosunda görüntülersiniz.
içindeControllers/StudentsController.cs
, Ayrıntılar görünümünün eylem yöntemi tek Student
bir varlığı almak için yöntemini kullanırFirstOrDefaultAsync
. çağıran Include
kodu ekleyin. ThenInclude
AsNoTracking
ve yöntemleri, aşağıdaki vurgulanmış kodda gösterildiği gibi.
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var student = await _context.Students
.Include(s => s.Enrollments)
.ThenInclude(e => e.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (student == null)
{
return NotFound();
}
return View(student);
}
Include
ve ThenInclude
yöntemleri, bağlamın gezinti özelliğini yüklemesine Student.Enrollments
ve her kayıtta gezinti özelliğinin Enrollment.Course
içine neden olur. İlgili verileri okuma öğreticisinde bu yöntemler hakkında daha fazla bilgi edineceksiniz.
yöntemi, AsNoTracking
döndürülen varlıkların geçerli bağlamın ömrü boyunca güncelleştirilmeyeceği senaryolarda performansı artırır. Bu öğreticinin sonunda hakkında AsNoTracking
daha fazla bilgi edineceksiniz.
Veri yönlendirme
yöntemine Details
geçirilen anahtar değeri yol verilerinden gelir. Yönlendirme verileri, model bağlayıcısının URL'nin bir kesiminde bulduğu verilerdir. Örneğin, varsayılan yol denetleyici, eylem ve kimlik kesimlerini belirtir:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Aşağıdaki URL'de varsayılan yol Eğitmen'i denetleyici, Eylem olarak Dizin'i ve kimlik olarak 1'i eşler; bunlar rota verisi değerleridir.
http://localhost:1230/Instructor/Index/1?courseID=2021
URL'nin ("?courseID=2021") son bölümü bir sorgu dizesi değeridir. Model bağlayıcısı, id değerini sorgu dizesi değeri Index
olarak geçirirseniz yöntem id
parametresine de geçirir:
http://localhost:1230/Instructor/Index?id=1&CourseID=2021
Dizin sayfasında, köprü URL'leri görünümdeki Razor etiket yardımcı deyimleri tarafından oluşturulur. Aşağıdaki Razor kodda id
parametresi varsayılan yol ile eşleşir, bu nedenle id
yol verilerine eklenir.
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a>
Bu, 6 olduğunda item.ID
aşağıdaki HTML'yi oluşturur:
<a href="/Students/Edit/6">Edit</a>
Aşağıdaki Razor kodda, studentID
varsayılan yoldaki bir parametreyle eşleşmediğinden sorgu dizesi olarak eklenir.
<a asp-action="Edit" asp-route-studentID="@item.ID">Edit</a>
Bu, 6 olduğunda item.ID
aşağıdaki HTML'yi oluşturur:
<a href="/Students/Edit?studentID=6">Edit</a>
Etiket yardımcıları hakkında daha fazla bilgi için bkz . ASP.NET Core'da Etiket Yardımcıları.
Ayrıntılar görünümüne kayıt ekleme
Views/Students/Details.cshtml
'ı açın. Her alan, aşağıdaki örnekte gösterildiği gibi ve DisplayFor
yardımcıları kullanılarak DisplayNameFor
görüntülenir:
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.LastName)
</dd>
Son alandan sonra ve kapanış </dl>
etiketinden hemen önce, kayıtların listesini görüntülemek için aşağıdaki kodu ekleyin:
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Enrollments)
</dt>
<dd class="col-sm-10">
<table class="table">
<tr>
<th>Course Title</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Enrollments)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Course.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
</dd>
Kodu yapıştırdıktan sonra kod girintisi yanlışsa, düzeltmek için CTRL-K-D tuşlarına basın.
Bu kod, gezinti özelliğindeki Enrollments
varlıklar arasında döngü oluşturur. Her kayıt için kurs başlığını ve notu görüntüler. Kurs başlığı, Kayıtlar varlığının gezinti özelliğinde Course
depolanan Kurs varlığından alınır.
Uygulamayı çalıştırın, Öğrenciler sekmesini seçin ve bir öğrencinin Ayrıntılar bağlantısına tıklayın. Seçilen öğrencinin ders ve not listesini görürsünüz:
Oluştur sayfasını güncelleştirme
içindeStudentsController.cs
, try-catch bloğu ekleyerek ve özniteliğinden Bind
kimliği kaldırarak HttpPost Create
yöntemini değiştirin.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("EnrollmentDate,FirstMidName,LastName")] Student student)
{
try
{
if (ModelState.IsValid)
{
_context.Add(student);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists " +
"see your system administrator.");
}
return View(student);
}
Bu kod, ASP.NET Core MVC model bağlayıcısı tarafından oluşturulan Öğrenci varlığını Öğrenciler varlık kümesine ekler ve ardından değişiklikleri veritabanına kaydeder. (Model bağlayıcısı, form tarafından gönderilen verilerle çalışmanızı kolaylaştıran ASP.NET Core MVC işlevselliğini ifade eder; model bağlayıcısı gönderilen form değerlerini CLR türlerine dönüştürür ve bunları parametrelerdeki eylem yöntemine geçirir. Bu durumda model bağlayıcısı, Form koleksiyonundaki özellik değerlerini kullanarak sizin için bir Student varlığının örneğini oluşturur.)
Kimlik, satır eklendiğinde SQL Server'ın otomatik olarak ayarlanacağı birincil anahtar değeri olduğundan özniteliğinden Bind
kaldırdınızID
. Kullanıcıdan gelen giriş kimlik değerini ayarlamaz.
özniteliği dışında Bind
, iskelesi oluşturulmuş kodda yaptığınız tek değişiklik try-catch bloğudur. Değişiklikleri kaydedilirken türetilen DbUpdateException
bir özel durum yakalanırsa, genel bir hata iletisi görüntülenir. DbUpdateException
özel durumlar bazen programlama hatası yerine uygulamanın dışındaki bir şeyden kaynaklanır, bu nedenle kullanıcının yeniden denemesi tavsiye edilir. Bu örnekte uygulanmasa da, bir üretim kalitesi uygulaması özel durumu günlüğe kaydeder. Daha fazla bilgi için İzleme ve Telemetri (Azure ile Gerçek Dünya Bulut Uygulamaları Oluşturma) bölümündeki İçgörü günlüğü bölümüne bakın.
özniteliği siteler ValidateAntiForgeryToken
arası istek sahteciliği (CSRF) saldırılarını önlemeye yardımcı olur. Belirteç, FormTagHelper tarafından görünüme otomatik olarak eklenir ve form kullanıcı tarafından gönderildiğinde eklenir. Belirteç özniteliği tarafından ValidateAntiForgeryToken
doğrulanır. Daha fazla bilgi için, bkz. ASP.NET Core'da Siteler Arası İstek Sahteciliği (XSRF/CSRF) saldırılarını önleme.
Fazla paylaşımla ilgili güvenlik notu
Bind
yapı iskelesi oluşturulmuş kodun yönteminde Create
içerdiği öznitelik, oluşturma senaryolarında aşırı paylaşıma karşı korumanın bir yoludur. Örneğin, Öğrenci varlığının bu web sayfasının ayarlamasını istemediğiniz bir Secret
özellik içerdiğini varsayalım.
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public string Secret { get; set; }
}
Web sayfasında bir Secret
alanınız olmasa bile, bir bilgisayar korsanı form değeri göndermek Secret
için Fiddler gibi bir araç kullanabilir veya javascript yazabilir. Bind
Öznitelik, model bağlayıcısının Öğrenci örneği oluştururken kullandığı alanları sınırlamadan, model bağlayıcısı bu Secret
form değerini alır ve Student varlık örneğini oluşturmak için kullanır. Ardından, hacker'ın form alanı için Secret
belirttiği değer veritabanınızda güncelleştirilir. Aşağıdaki görüntüde, fiddler aracının gönderilen form değerlerine Secret
alanı ("OverPost" değeriyle) eklemesi gösterilmektedir.
"OverPost" değeri daha sonra eklenen satırın Secret
özelliğine başarıyla eklenir, ancak web sayfasının bu özelliği ayarlayabilmesini hiç amaçlamadıysanız.
Düzenleme senaryolarında, varlığı önce veritabanından okuyup, sonra açıkça izin verilen özellikler listesini geçirerek çağırarak TryUpdateModel
fazla paylaşım yapılmasını önleyebilirsiniz. Bu, bu öğreticilerde kullanılan yöntemdir.
Birçok geliştirici tarafından tercih edilen fazla göndermeyi önlemenin alternatif bir yolu, model bağlama ile varlık sınıfları yerine görünüm modellerini kullanmaktır. Görünüm modeline yalnızca güncelleştirmek istediğiniz özellikleri ekleyin. MVC model bağlayıcısı tamamlandıktan sonra, isteğe bağlı olarak AutoMapper gibi bir araç kullanarak görünüm modeli özelliklerini varlık örneğine kopyalayın. Varlık örneğinde durumunu olarak ve Unchanged
ardından görünüm modeline dahil edilen her varlık özelliğinde true olarak ayarlamak Property("PropertyName").IsModified
için kullanın_context.Entry
. Bu yöntem hem düzenleme hem de oluşturma senaryolarında çalışır.
Oluştur sayfasını test edin
içindeki Views/Students/Create.cshtml
kod, her alan için , input
ve span
(doğrulama iletileri için) etiket yardımcılarını kullanırlabel
.
Uygulamayı çalıştırın, Öğrenciler sekmesini seçin ve Yeni Oluştur'a tıklayın.
Adları ve tarihi girin. Tarayıcınız bunu yapmanıza izin veriyorsa geçersiz bir tarih girmeyi deneyin. (Bazı tarayıcılar sizi tarih seçici kullanmaya zorlar.) Ardından, hata iletisini görmek için Oluştur'a tıklayın.
Bu, varsayılan olarak elde ettiğiniz sunucu tarafı doğrulamadır; sonraki bir öğreticide, istemci tarafı doğrulaması için kod oluşturacak özniteliklerin nasıl ekleneceğini göreceksiniz. Aşağıdaki vurgulanmış kod, yöntemindeki model doğrulama denetimini Create
gösterir.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
[Bind("EnrollmentDate,FirstMidName,LastName")] Student student)
{
try
{
if (ModelState.IsValid)
{
_context.Add(student);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists " +
"see your system administrator.");
}
return View(student);
}
Tarihi geçerli bir değerle değiştirin ve Yeni öğrencinin Dizin sayfasında görünmesi için Oluştur'a tıklayın.
Düzenle sayfasını güncelleştirme
içinde StudentController.cs
HttpGet Edit
yöntemi (özniteliği olmayanHttpPost
) yönteminde gördüğünüz Details
gibi seçili Student varlığını almak için yöntemini kullanırFirstOrDefaultAsync
. Bu yöntemi değiştirmeniz gerekmez.
Önerilen HttpPost Düzenleme kodu: Okuma ve güncelleştirme
HttpPost Edit eylem yöntemini aşağıdaki kodla değiştirin.
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditPost(int? id)
{
if (id == null)
{
return NotFound();
}
var studentToUpdate = await _context.Students.FirstOrDefaultAsync(s => s.ID == id);
if (await TryUpdateModelAsync<Student>(
studentToUpdate,
"",
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
try
{
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
}
return View(studentToUpdate);
}
Bu değişiklikler, fazla paylaşım yapılmasını önlemek için en iyi güvenlik uygulamasını uygular. İskele bir Bind
öznitelik oluşturdu ve model bağlayıcısı tarafından oluşturulan varlığı bir Modified
bayrakla varlık kümesine ekledi. Özniteliği parametrede listelenmeyen Bind
Include
alanlardaki önceden var olan verileri temizlediğinden bu kod birçok senaryo için önerilmez.
Yeni kod, mevcut varlığı okur ve gönderilen form verilerindeki kullanıcı girişine göre alınan varlıktaki alanları güncelleştirmek için çağrılarTryUpdateModel
. Entity Framework'ün otomatik değişiklik izlemesi, form girişi tarafından değiştirilen alanlarda bayrağı ayarlar Modified
. SaveChanges
Yöntemi çağrıldığında, Entity Framework veritabanı satırını güncelleştirmek için SQL deyimleri oluşturur. Eşzamanlılık çakışmaları yoksayılır ve veritabanında yalnızca kullanıcı tarafından güncelleştirilen tablo sütunları güncelleştirilir. (Sonraki bir öğreticide eşzamanlılık çakışmalarının nasıl işleneceğini gösterilmektedir.)
Fazla göndermeyi önlemek için en iyi yöntem olarak, Düzenle sayfası tarafından güncelleştirilebilir olmasını istediğiniz alanlar parametrelerde TryUpdateModel
bildirilir. (Parametre listesindeki alan listesinden önce gelen boş dize, form alanları adlarıyla kullanılacak bir ön ek içindir.) Şu anda koruduğun ek alan yok, ancak model bağlayıcısının bağlamasını istediğiniz alanları listelemek, gelecekte veri modeline alanlar eklerseniz, bunları buraya açıkça ekleyene kadar bunların otomatik olarak korunmasını sağlar.
Bu değişikliklerin sonucunda, HttpPost Edit
yönteminin yöntem imzası HttpGet Edit
yöntemiyle aynıdır; bu nedenle yöntemini EditPost
yeniden adlandırmışsınızdır.
Alternatif HttpPost Düzenleme kodu: Oluşturma ve ekleme
Önerilen HttpPost düzenleme kodu, yalnızca değiştirilen sütunların güncelleştirilmesini sağlar ve model bağlama için eklenmesini istemediğiniz özelliklerdeki verileri korur. Ancak, ilk okuma yaklaşımı fazladan bir veritabanı okuması gerektirir ve eşzamanlılık çakışmalarını işlemek için daha karmaşık bir koda neden olabilir. Alternatif olarak, model bağlayıcısı tarafından oluşturulan bir varlığı EF bağlamı'na iliştirip değiştirilmiş olarak işaretlemek de kullanılabilir. (Projenizi bu kodla güncelleştirin, yalnızca isteğe bağlı bir yaklaşımı göstermek için gösterilir.)
public async Task<IActionResult> Edit(int id, [Bind("ID,EnrollmentDate,FirstMidName,LastName")] Student student)
{
if (id != student.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(student);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
}
return View(student);
}
Web sayfası kullanıcı arabirimi varlıktaki tüm alanları içerdiğinde ve bunlardan herhangi birini güncelleştirebildiğinde bu yaklaşımı kullanabilirsiniz.
yapı iskelesi oluşturulmuş kod oluşturma ve ekleme yaklaşımını kullanır, ancak yalnızca özel durumları yakalar DbUpdateConcurrencyException
ve 404 hata kodu döndürür. Gösterilen örnek tüm veritabanı güncelleştirme özel durumlarını yakalar ve bir hata iletisi görüntüler.
Varlık Durumları
Veritabanı bağlamı, bellekteki varlıkların veritabanında karşılık gelen satırlarıyla eşitlenip eşitlenmediğini izler ve bu bilgiler yöntemi çağırdığınızda SaveChanges
ne olacağını belirler. Örneğin, yöntemine Add
yeni bir varlık geçirdiğinizde, bu varlığın durumu olarak Added
ayarlanır. Ardından yöntemini çağırdığınızda SaveChanges
veritabanı bağlamı bir SQL INSERT komutu döndürür.
Bir varlık aşağıdaki durumlardan birinde olabilir:
Added
. Varlık henüz veritabanında yok.SaveChanges
yöntemi bir INSERT deyimi oluşturur.Unchanged
. yöntemiyle bu varlıklaSaveChanges
hiçbir şey yapılmasına gerek yoktur. Veritabanından bir varlığı okuduğunuzda varlık bu durumla başlar.Modified
. Varlığın özellik değerlerinin bazıları veya tümü değiştirildi.SaveChanges
yöntemi bir UPDATE deyimi oluşturur.Deleted
. Varlık silinmek üzere işaretlendi.SaveChanges
yöntemi bir DELETE deyimi oluşturur.Detached
. Varlık veritabanı bağlamı tarafından izlenmiyor.
Masaüstü uygulamasında durum değişiklikleri genellikle otomatik olarak ayarlanır. Bir varlığı okur ve bazı özellik değerlerinde değişiklik yaparsınız. Bu, varlık durumunun otomatik olarak olarak olarak değiştirilmesine Modified
neden olur. Ardından çağırdığınızda SaveChanges
, Entity Framework yalnızca değiştirdiğiniz gerçek özellikleri güncelleştiren bir SQL UPDATE deyimi oluşturur.
Bir web uygulamasında, DbContext
başlangıçta bir varlığı okuyan ve düzenlenecek verilerini görüntüleyen, sayfa işlendikten sonra atılır. HttpPost Edit
eylem yöntemi çağrıldığında, yeni bir web isteği yapılır ve yeni bir örneğine DbContext
sahipsiniz. Varlığı bu yeni bağlamda yeniden okursanız masaüstü işleme benzetimi yapılır.
Ancak ek okuma işlemini yapmak istemiyorsanız, model bağlayıcısı tarafından oluşturulan varlık nesnesini kullanmanız gerekir. Bunu yapmanın en basit yolu, daha önce gösterilen alternatif HttpPost Düzenleme kodunda olduğu gibi varlık durumunu Değiştirildi olarak ayarlamaktır. Ardından öğesini çağırdığınızda SaveChanges
, bağlamın hangi özellikleri değiştirdiğiniz hakkında hiçbir bilgisi olmadığından Entity Framework veritabanı satırının tüm sütunlarını güncelleştirir.
İlk okuma yaklaşımından kaçınmak, ancak SQL UPDATE deyiminin yalnızca kullanıcının gerçekten değiştirdiği alanları güncelleştirmesini istiyorsanız, kod daha karmaşıktır. HttpPost Edit
yöntemi çağrıldığında kullanılabilir olmaları için özgün değerleri bir şekilde (örneğin, gizli alanları kullanarak) kaydetmeniz gerekir. Ardından, özgün değerleri kullanarak bir Student varlığı oluşturabilir, varlığın Attach
özgün sürümüyle yöntemini çağırabilir, varlığın değerlerini yeni değerlerle güncelleştirebilir ve ardından öğesini çağırabilirsiniz SaveChanges
.
Düzenleme sayfasını test edin
Uygulamayı çalıştırın, Öğrenciler sekmesini seçin ve ardından Bir Köprüyü düzenle'ye tıklayın.
Bazı verileri değiştirin ve Kaydet'e tıklayın. Dizin sayfası açılır ve değiştirilen verileri görürsünüz.
Sil sayfasını güncelleştirme
içinde StudentController.cs
, HttpGet Delete
yönteminin şablon kodu, Ayrıntılar ve Düzenleme yöntemlerinde gördüğünüz gibi seçili Student varlığını almak için yöntemini kullanır FirstOrDefaultAsync
. Ancak çağrısı başarısız olduğunda özel bir hata iletisi uygulamak için SaveChanges
bu yönteme ve ilgili görünümüne bazı işlevler ekleyeceksiniz.
Güncelleştirme ve oluşturma işlemlerini gördüğünüz gibi silme işlemleri için iki eylem yöntemi gerekir. GET isteğine yanıt olarak çağrılan yöntem, kullanıcıya silme işlemini onaylama veya iptal etme şansı veren bir görünüm görüntüler. Kullanıcı onaylarsa bir POST isteği oluşturulur. Böyle bir durumda HttpPost Delete
yöntemi çağrılır ve bu yöntem silme işlemini gerçekleştirir.
Veritabanı güncelleştirildiğinde oluşabilecek hataları işlemek için HttpPost Delete
yöntemine bir try-catch bloğu ekleyeceksiniz. Bir hata oluşursa, HttpPost Delete yöntemi HttpGet Delete yöntemini çağırır ve bir hata oluştuğuna işaret eden bir parametre iletir. HttpGet Delete yöntemi daha sonra hata iletisiyle birlikte onay sayfasını yeniden dağıtarak kullanıcıya iptal etme veya yeniden deneme fırsatı verir.
HttpGet Delete
eylem yöntemini, hata raporlamayı yöneten aşağıdaki kodla değiştirin.
public async Task<IActionResult> Delete(int? id, bool? saveChangesError = false)
{
if (id == null)
{
return NotFound();
}
var student = await _context.Students
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (student == null)
{
return NotFound();
}
if (saveChangesError.GetValueOrDefault())
{
ViewData["ErrorMessage"] =
"Delete failed. Try again, and if the problem persists " +
"see your system administrator.";
}
return View(student);
}
Bu kod, yöntemin değişiklikleri kaydetme hatasından sonra çağrılıp çağrılmadığını gösteren isteğe bağlı bir parametreyi kabul eder. HttpGet Delete
yöntemi önceki bir hata olmadan çağrıldığında bu parametre false olur. Veritabanı güncelleştirme hatasına yanıt olarak HttpPost Delete
yöntemi tarafından çağrıldığında parametresi true olur ve görünüme bir hata iletisi geçirilir.
HttpPost Delete'e ilk okuma yaklaşımı
HttpPost Delete
eylem yöntemini (adlı DeleteConfirmed
) gerçek silme işlemini gerçekleştiren ve veritabanı güncelleştirme hatalarını yakalayan aşağıdaki kodla değiştirin.
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var student = await _context.Students.FindAsync(id);
if (student == null)
{
return RedirectToAction(nameof(Index));
}
try
{
_context.Students.Remove(student);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction(nameof(Delete), new { id = id, saveChangesError = true });
}
}
Bu kod seçili varlığı alır ve varlığın Remove
durumunu Deleted
olarak ayarlamak için yöntemini çağırır. Çağrıldığında SaveChanges
bir SQL DELETE komutu oluşturulur.
HttpPost Delete'e oluşturma ve ekleme yaklaşımı
Yüksek hacimli bir uygulamada performansı geliştirmek öncelikliyse, yalnızca birincil anahtar değerini kullanarak bir Student varlığının örneğini oluşturup varlık durumunu Deleted
olarak ayarlayarak gereksiz bir SQL sorgusundan kaçınabilirsiniz. Varlığı silmek için Entity Framework'e gerekenler bunlardır. (Bu kodu projenize koymayın; yalnızca alternatif bir kod göstermek için buradadır.)
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
try
{
Student studentToDelete = new Student() { ID = id };
_context.Entry(studentToDelete).State = EntityState.Deleted;
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction(nameof(Delete), new { id = id, saveChangesError = true });
}
}
Varlığın da silinmesi gereken ilgili verileri varsa, veritabanında art arda silmenin yapılandırıldığından emin olun. Varlık silmeye yönelik bu yaklaşımla EF, silinecek ilgili varlıklar olduğunu fark etmeyebilir.
Sil görünümünü güncelleştirme
içinde Views/Student/Delete.cshtml
, aşağıdaki örnekte gösterildiği gibi h2 başlığı ile h3 başlığı arasına bir hata iletisi ekleyin:
<h2>Delete</h2>
<p class="text-danger">@ViewData["ErrorMessage"]</p>
<h3>Are you sure you want to delete this?</h3>
Uygulamayı çalıştırın, Öğrenciler sekmesini seçin ve Bir Köprüyü sil'e tıklayın:
Sil'e tıklayın. Dizin sayfası, silinen öğrenci olmadan görüntülenir. (Eşzamanlılık öğreticisinde hata işleme kodunun bir örneğini çalışır durumda görürsünüz.)
Veritabanı bağlantılarını kapatma
Veritabanı bağlantısının barındırıldığı kaynakları boşaltmak için, bağlam örneğinin işiniz bittiğinde mümkün olan en kısa sürede atılması gerekir. ASP.NET Core yerleşik bağımlılık ekleme işlemi bu görevi sizin için halleder.
içindeStartup.cs
, sınıfı ASP.NET Core DI kapsayıcısında sağlamak DbContext
için AddDbContext uzantısı yöntemini çağırırsınız. Bu yöntem, hizmet ömrünü varsayılan olarak olarak Scoped
olarak ayarlar. Scoped
, bağlam nesnesinin yaşam süresinin web isteği yaşam süresiyle aynı olduğu ve yöntemin Dispose
web isteğinin sonunda otomatik olarak çağrılacağı anlamına gelir.
İşlemleri işleme
Varsayılan olarak Entity Framework işlemleri örtük olarak uygular. Birden çok satır veya tabloda değişiklik yaptığınız ve ardından öğesini çağırdığınız SaveChanges
senaryolarda, Entity Framework otomatik olarak tüm değişikliklerinizin başarılı olmasını veya tümünün başarısız olmasını sağlar. Önce bazı değişiklikler yapılır ve sonra bir hata oluşursa, bu değişiklikler otomatik olarak geri alınır. Daha fazla denetime ihtiyacınız olan senaryolar için (örneğin, bir işleme Entity Framework dışında yapılan işlemleri dahil etmek istiyorsanız) bkz . İşlemler.
İzlemesiz sorgular
Veritabanı bağlamı tablo satırlarını aldığında ve bunları temsil eden varlık nesneleri oluşturduğunda, varsayılan olarak bellekteki varlıkların veritabanındakilerle eşitlenmiş olup olmadığını izler. Bellekteki veriler önbellek görevi görür ve varlığı güncelleştirdiğinizde kullanılır. Bağlam örnekleri genellikle kısa süreli (her istek için yeni bir tane oluşturulur ve atılır) ve bir varlığı okuyan bağlam genellikle bu varlık yeniden kullanılmadan önce atıldığından, bu önbelleğe alma genellikle bir web uygulamasında gereksizdir.
yöntemini çağırarak bellekteki varlık nesnelerinin izlenmesini AsNoTracking
devre dışı bırakabilirsiniz. Bunu yapmak isteyebileceğiniz tipik senaryolar şunlardır:
Bağlam ömrü boyunca hiçbir varlığı güncelleştirmeniz gerekmez ve EF'nin gezinti özelliklerini ayrı sorgular tarafından alınan varlıklarla otomatik olarak yüklemesi gerekmez. Bu koşullar genellikle denetleyicinin HttpGet eylem yöntemlerinde karşılanıyor.
Büyük miktarda veri alan bir sorgu çalıştırıyorsanız, döndürülen verilerin yalnızca küçük bir kısmı güncelleştirilecektir. Büyük sorgu için izlemeyi kapatmak ve daha sonra güncelleştirililmesi gereken birkaç varlık için bir sorgu çalıştırmak daha verimli olabilir.
Güncelleştirmek için bir varlık eklemek istiyorsunuz, ancak daha önce aynı varlığı farklı bir amaç için aldıysanız. Varlık veritabanı bağlamı tarafından zaten izlendiğinden, değiştirmek istediğiniz varlığı ekleyemezsiniz. Bu durumu işlemenin bir yolu, önceki sorguda çağırmaktır
AsNoTracking
.
Daha fazla bilgi için bkz . İzleme ve İzleme Yok.
Kodu alma
Tamamlanan uygulamayı indirin veya görüntüleyin.
Sonraki adımlar
Bu öğreticide şunları yaptınız:
- Ayrıntılar sayfası özelleştirildi
- Oluştur sayfası güncelleştirildi
- Düzenle sayfası güncelleştirildi
- Sil sayfası güncelleştirildi
- Kapalı veritabanı bağlantıları
Sıralama, filtreleme ve sayfalama ekleyerek Dizin sayfasının işlevselliğini genişletmeyi öğrenmek için sonraki öğreticiye ilerleyin.
ASP.NET Core