Öğretici: Gelişmiş senaryolar hakkında bilgi ASP.NET MVC'yi EF Core
Önceki öğreticide hiyerarşi başına tablo devralmayı uygulamaya koyarak. Bu öğreticide, ASP.NET Core kullanan web uygulamaları geliştirmenin temellerini Entity Framework Core.
Bu öğreticide şunları yaptınız:
- Ham SQL gerçekleştirme
- Varlıkları iade etmek için sorgu çağırma
- Diğer türleri geri dönmek için sorgu çağırma
- Güncelleştirme sorgusu çağırma
- Sorgu SQL inceleme
- Soyutlama katmanı oluşturma
- Otomatik değişiklik algılama hakkında bilgi
- Kaynak kodu EF Core geliştirme planları hakkında bilgi edinmek için
- Kodu basitleştirmek için dinamik LINQ kullanmayı öğrenin
Önkoşullar
Ham SQL gerçekleştirme
Bu yöntemi kullanmanın avantajlarından Entity Framework, kodunuzu belirli bir veri depolama yöntemine çok yakın bir şekilde depolamaktan kaçınmasıdır. Bu, sizin SQL sorgular ve komutlar oluşturmanın yanı sıra bunları kendiniz yazmak zorunda kalmadan sizi serbest bırakarak yapar. Ancak el ile oluşturduğunuz belirli sorgular için belirli SQL olağanüstü senaryolar vardır. Bu senaryolar için Entity Framework Code First API'si, komutlarını doğrudan veritabanına SQL yöntemler içerir. 1.0'EF Core seçenekleriniz vardır:
Varlık
DbSet.FromSqltürlerine dönüşen sorgular için yöntemini kullanın. Döndürülen nesneler nesne tarafından beklenen türde olmalıdır ve izlemeyi kapatmadıkça bunlar veritabanıDbSetbağlamı tarafından otomatik olarak izlenir.Sorgu
Database.ExecuteSqlCommandolmayan komutlar için kullanın.
Varlık olmayan türleri döndüren bir sorgu çalıştırmanız gerekirse, bu sorguyu EF tarafından ADO.NET veritabanı bağlantısıyla birlikte kullanabilirsiniz. Döndürülen veriler, varlık türlerini almak için bu yöntemi kullansanız bile veritabanı bağlamı tarafından iz değildir.
Her zaman olduğu gibi, bir web SQL komutlarını yürütürken, sitenizi yeni ekleme saldırılarına karşı korumak için SQL gerekir. Bunu yapmak için parametreli sorgular kullanarak web sayfası tarafından gönderilen dizelerin tek bir komut olarak yorumlanamay SQL gerekir. Bu öğreticide, kullanıcı girişini bir sorguyla tümleştirirken parametreli sorguları kullanıcaz.
Varlıkları iade etmek için sorgu çağırma
sınıfı DbSet<TEntity> türünde bir varlık döndüren bir sorgu yürütmek için kullanabileceğiniz bir yöntem TEntity sağlar. Bunun nasıl çalıştığını görmek için Bölüm denetleyicisinin Details yönteminde kodu değiştireceksiniz.
DepartmentsController.cs içinde, yönteminde, aşağıdaki vurgulanan kodda gösterildiği gibi, bir bölümü alan kodu bir yöntem Details FromSql çağrısıyla değiştirin:
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
string query = "SELECT * FROM Department WHERE DepartmentID = {0}";
var department = await _context.Departments
.FromSql(query, id)
.Include(d => d.Administrator)
.AsNoTracking()
.FirstOrDefaultAsync();
if (department == null)
{
return NotFound();
}
return View(department);
}
Yeni kodun düzgün çalıştığını doğrulamak için Departmanlar sekmesini ve ardından departmanlardan birinin Ayrıntılar'ı seçin.

Diğer türleri geri dönmek için sorgu çağırma
Daha önce Hakkında sayfası için her kayıt tarihi için öğrenci sayısını gösteren bir öğrenci istatistikleri kılavuzu oluşturdunız. Students varlık kümesinden ( ) verileri aldı ve sonuçları görünüm modeli nesneleri listesine projek için _context.Students LINQ EnrollmentDateGroup kullandın. LINQ kullanmak yerine SQL yazmak istediğinizi varsayalım. Bunu yapmak için varlık nesneleri dışında bir SQL döndüren bir sorgu çalıştırmalısınız. 1 EF Core 1.0'da bunu yapmak için bir ADO.NET kodu yazmak ve EF'den veritabanı bağlantısını almaktır.
Home Controller.cs içinde yöntemini About aşağıdaki kodla değiştirin:
public async Task<ActionResult> About()
{
List<EnrollmentDateGroup> groups = new List<EnrollmentDateGroup>();
var conn = _context.Database.GetDbConnection();
try
{
await conn.OpenAsync();
using (var command = conn.CreateCommand())
{
string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount "
+ "FROM Person "
+ "WHERE Discriminator = 'Student' "
+ "GROUP BY EnrollmentDate";
command.CommandText = query;
DbDataReader reader = await command.ExecuteReaderAsync();
if (reader.HasRows)
{
while (await reader.ReadAsync())
{
var row = new EnrollmentDateGroup { EnrollmentDate = reader.GetDateTime(0), StudentCount = reader.GetInt32(1) };
groups.Add(row);
}
}
reader.Dispose();
}
}
finally
{
conn.Close();
}
return View(groups);
}
Using deyimi ekleyin:
using System.Data.Common;
Uygulamayı çalıştırın ve Hakkında sayfasına gidin. Daha önce de aynı verileri görüntüler.

Güncelleştirme sorgusu çağırma
Contoso Üniversitesi yöneticilerinin veritabanında her kurs için kredi sayısını değiştirme gibi genel değişiklikler yapmak istiyor olduğunu varsayalım. Üniversitenin çok sayıda kursu varsa bunların hepsini varlık olarak almak ve bunları tek tek değiştirmek verimsiz olabilir. Bu bölümde, kullanıcının tüm kurslar için kredi sayısını değiştirerek bir faktör belirtmesine olanak sağlayan bir web sayfası uygulayacak ve SQL UPDATE deyimini yürüterek değişikliği yapacaktır. Web sayfası aşağıdaki şekilde görünür:

CoursesController.cs içinde, HttpGet ve HttpPost için UpdateCourseCredits yöntemlerini ekleyin:
public IActionResult UpdateCourseCredits()
{
return View();
}
[HttpPost]
public async Task<IActionResult> UpdateCourseCredits(int? multiplier)
{
if (multiplier != null)
{
ViewData["RowsAffected"] =
await _context.Database.ExecuteSqlCommandAsync(
"UPDATE Course SET Credits = Credits * {0}",
parameters: multiplier);
}
return View();
}
Denetleyici bir HttpGet isteğini işlemesi sırasında içinde hiçbir şey döndürülecek değildir ve görünümde, önceki çizimde gösterildiği gibi boş bir metin kutusu ve gönder ViewData["RowsAffected"] düğmesi görüntülenir.
Güncelleştir düğmesine tıkıldığında HttpPost yöntemi çağrılır ve çarpan metin kutusuna girilen değeri içerir. Kod daha sonra dersleri SQL ve etkilenen satır sayısını görünümündeki görünüme döndüren kodu ViewData yürütür. Görünüm bir değer RowsAffected alır ve güncelleştirilmiş satır sayısını görüntüler.
Bu Çözüm Gezgini Görünümler/Kurslar klasörüne sağ tıklayın ve ardından Yeni Öğeye Ekle'> tıklayın.
Yeni Öğe Ekle iletişim kutusunda, sol bölmede yüklü altındaki ASP.NET Core'ye tıklayın, Görünüm'e tıklayın ve yeni görünümü UpdateCourseCredits.cshtml olarak adlandı. Razor
Views/Courses/UpdateCourseCredits.cshtml içinde şablon kodunu aşağıdaki kodla değiştirin:
@{
ViewBag.Title = "UpdateCourseCredits";
}
<h2>Update Course Credits</h2>
@if (ViewData["RowsAffected"] == null)
{
<form asp-action="UpdateCourseCredits">
<div class="form-actions no-color">
<p>
Enter a number to multiply every course's credits by: @Html.TextBox("multiplier")
</p>
<p>
<input type="submit" value="Update" class="btn btn-default" />
</p>
</div>
</form>
}
@if (ViewData["RowsAffected"] != null)
{
<p>
Number of rows updated: @ViewData["RowsAffected"]
</p>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Kurslar sekmesini seçerek yöntemini çalıştırın ve ardından tarayıcının adres UpdateCourseCredits çubuğundaki URL'nin sonuna "/UpdateCourseCredits" ekleyin (örneğin: http://localhost:5813/Courses/UpdateCourseCredits ). Metin kutusuna bir sayı girin:

Güncelleştir’e tıklayın. Etkilenen satır sayısını görüyorsunuz:

Düzeltilmiş kredi sayısına sahip kurs listesini görmek için Listeye Geri Dön'e tıklayın.
Üretim kodunun güncelleştirmelerin her zaman geçerli verilerle sonuçlandır olmasını sağlar. Burada gösterilen basitleştirilmiş kod, kredi sayısını 5'in üzerinde sayılarla sonuçlandıracak kadar çarpabilir. Credits(Özelliğin bir özniteliği [Range(0, 5)] vardır.) Güncelleştirme sorgusu çalışır ancak geçersiz veriler, sistemin kredi sayısının 5 veya daha düşük olduğunu varsayan diğer kısımlarda beklenmeyen sonuçlara neden olabilir.
Ham sorgular hakkında daha fazla SQL için bkz. Ham SQL Sorguları.
Sorgu SQL inceleme
Bazen veritabanına gönderilen gerçek sorgu SQL görmek yararlı olabilir. ASP.NET Core için yerleşik günlük EF Core, sorgular ve güncelleştirmeler için SQL günlükler yazmak için otomatik olarak kullanılır. Bu bölümde günlük kaydıyla ilgili bazı SQL bulabilirsiniz.
StudentsController.cs'yi açın Details ve yönteminde deyiminde bir kesme noktası if (student == null) ayarlayın.
Uygulamayı hata ayıklama modunda çalıştırın ve bir öğrencinin Ayrıntılar sayfasına gidin.
Hata ayıklama çıkışını gösteren Çıkış penceresine gidin ve sorguyu görebilirsiniz:
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (56ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
SELECT TOP(2) [s].[ID], [s].[Discriminator], [s].[FirstName], [s].[LastName], [s].[EnrollmentDate]
FROM [Person] AS [s]
WHERE ([s].[Discriminator] = N'Student') AND ([s].[ID] = @__id_0)
ORDER BY [s].[ID]
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (122ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
SELECT [s.Enrollments].[EnrollmentID], [s.Enrollments].[CourseID], [s.Enrollments].[Grade], [s.Enrollments].[StudentID], [e.Course].[CourseID], [e.Course].[Credits], [e.Course].[DepartmentID], [e.Course].[Title]
FROM [Enrollment] AS [s.Enrollments]
INNER JOIN [Course] AS [e.Course] ON [s.Enrollments].[CourseID] = [e.Course].[CourseID]
INNER JOIN (
SELECT TOP(1) [s0].[ID]
FROM [Person] AS [s0]
WHERE ([s0].[Discriminator] = N'Student') AND ([s0].[ID] = @__id_0)
ORDER BY [s0].[ID]
) AS [t] ON [s.Enrollments].[StudentID] = [t].[ID]
ORDER BY [t].[ID]
Burada sizi şaşırtacak bir şey olduğunu fark SQL kişi tablosundan en fazla 2 satır ( TOP(2) ) seçer. yöntemi SingleOrDefaultAsync sunucuda 1 satıra çözümlemezse. Nedeni:
- Sorgu birden çok satır döndürse yöntemi null döndürür.
- Sorgunun birden çok satır döndürecek olup olmadığını belirlemek için EF'nin en az 2 satır döndürecek olup olmadığını denetlemesi gerekir.
Çıkış penceresinde günlüğe kaydetme çıkışını almak için hata ayıklama modunu kullanmanın ve kesme noktasıyla durdurmanın gerek olmadığını unutmayın. Yalnızca çıkışa bakmak istediğiniz noktada günlüğe kaydetmeyi durdurmanın kullanışlı bir yolu. Bunu yapmasanız da günlük kaydı devam eder ve ilgilendiğimiz bölümleri bulmak için geri kaydırmak zorunda oluruz.
Soyutlama katmanı oluşturma
Birçok geliştirici, depoyu ve iş birimi desenlerini kod çevresinde sarmalayıcı olarak uygulamak için kod yazar ve Entity Framework. Bu desenler, bir uygulamanın veri erişim katmanı ile iş mantığı katmanı arasında bir soyutlama katmanı oluşturmak için tasarlanmıştır. Bu desenlerin uygulanması, veri deposu değişikliklerinden uygulamanıza yardımcı olabilir ve otomatik birim testini veya test odaklı geliştirmeyi (TDD) kolaylaştırabilirsiniz. Ancak, bu desenleri uygulamak için ek kod yazmak, ef kullanan uygulamalar için her zaman en iyi seçenek değildir, çeşitli nedenlerle:
EF bağlam sınıfının kendisi kodunuzu veri deposuna özgü koddan yalıtır.
EF bağlam sınıfı, EF kullanarak veritabanı güncelleştirmeleri için bir iş birimi sınıfı olarak davranabilirsiniz.
EF, depo kodu yazmadan TDD uygulama özellikleri içerir.
Depoyu ve iş birimi desenlerini uygulama hakkında bilgi için bu öğretici serisinin Entity Framework 5 sürümüne bakın.
Entity Framework Core, test için kullanılan bir bellek içinde veritabanı sağlayıcısını uygulamaya alır. Daha fazla bilgi için bkz. InMemory ile test.
Otomatik değişiklik algılama
Bu Entity Framework, bir varlığın geçerli değerlerini özgün değerlerle karşılaştırarak bir varlığın nasıl değiştiğini (ve bu nedenle veritabanına hangi güncelleştirmelerin gönderildiğini) belirler. Varlık sorgulandığı veya ekli olduğu zaman özgün değerler depolanır. Otomatik değişiklik algılamaya neden olan yöntemlerden bazıları aşağıdakilerdir:
DbContext.SaveChanges
DbContext.Entry
ChangeTracker.Entries
Çok sayıda varlığı izliyorsanız ve döngüde bu yöntemlerden birini birçok kez çağırıyorsanız, özelliğini kullanarak otomatik değişiklik algılamayı geçici olarak kapatarak önemli performans geliştirmeleri ChangeTracker.AutoDetectChangesEnabled elde edersiniz. Örnek:
_context.ChangeTracker.AutoDetectChangesEnabled = false;
EF Core kodu ve geliştirme planlarını içerir
Kaynak Entity Framework Core kaynağındadır. https://github.com/dotnet/efcore Bu EF Core gecelik derlemeler, sorun izleme, özellik özellikleri, tasarım toplantı notları ve gelecekteki geliştirme için yol haritası içerir. Hataları dosyalar veya bulabilir ve katkıda bulunabilirsiniz.
Kaynak kod açık olsa da, Entity Framework Core microsoft ürünü olarak tam olarak de desteklense de. Microsoft Entity Framework ekibi, kabul edilen katkılar üzerinde denetime sahip olur ve her bir sürümün kalitesini sağlamak için tüm kod değişikliklerini test eder.
Mevcut veritabanından tersine mühendislik
Var olan bir veritabanındaki varlık sınıflarını içeren bir veri modelini tersine çevirmek için scaffold-dbcontext komutunu kullanın. Başlarken öğreticisi'ne bakın.
Kodu basitleştirmek için dinamik LINQ kullanma
Bu serinin üçüncü öğreticisinde, bir deyiminde sütun adlarını sabit kod yazarak LINQ kodunun nasıl yaz olduğu switch gösterir. seçilecek iki sütunla bu işe yarar, ancak çok sayıda sütun varsa kod ayrıntılı olabilir. Bu sorunu çözmek için yöntemini kullanarak EF.Property özelliğin adını dize olarak belirtebilirsiniz. Bu yaklaşımı denemek için içinde Index yöntemini aşağıdaki StudentsController kodla değiştirin.
public async Task<IActionResult> Index(
string sortOrder,
string currentFilter,
string searchString,
int? pageNumber)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["NameSortParm"] =
String.IsNullOrEmpty(sortOrder) ? "LastName_desc" : "";
ViewData["DateSortParm"] =
sortOrder == "EnrollmentDate" ? "EnrollmentDate_desc" : "EnrollmentDate";
if (searchString != null)
{
pageNumber = 1;
}
else
{
searchString = currentFilter;
}
ViewData["CurrentFilter"] = searchString;
var students = from s in _context.Students
select s;
if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}
if (string.IsNullOrEmpty(sortOrder))
{
sortOrder = "LastName";
}
bool descending = false;
if (sortOrder.EndsWith("_desc"))
{
sortOrder = sortOrder.Substring(0, sortOrder.Length - 5);
descending = true;
}
if (descending)
{
students = students.OrderByDescending(e => EF.Property<object>(e, sortOrder));
}
else
{
students = students.OrderBy(e => EF.Property<object>(e, sortOrder));
}
int pageSize = 3;
return View(await PaginatedList<Student>.CreateAsync(students.AsNoTracking(),
pageNumber ?? 1, pageSize));
}
Teşekkürler
Bu öğreticiyi Tom Dykstra ve Rick Anderson @RickAndMSFT (twitter) yazdı. Entity Framework ekibinin diğer üyeleri Rowan Miller ve Rowan Miller, kod incelemeleri konusunda yardımcı oldu ve öğreticiler için kod yazarken ortaya çıkan hata ayıklama sorunlarına yardımcı oldu. John Parente ve Paul Goldman, ASP.NET Core 2.2 için öğreticiyi güncelleştirme üzerinde çalıştı.
Sık karşılaşılan hataları giderme
ContosoUniversity.dll işlem tarafından kullanılan işlemler
Hata iletisi:
Yazmak için '...bin\Debug\netcoreapp1.0\ContosoUniversity.dll' açamıyor - 'İşlem başka bir işlem tarafından ...\bin\Debug\netcoreapp1.0\ContosoUniversity.dll' dosyasına erişe değil.
Çözüm:
Siteyi IIS Express. Windows System Tepsisi'ne gidin, IIS Express bulun ve simgesine sağ tıklayın, Contoso University sitesini seçin ve siteyi Durdur'a tıklayın.
Yukarı ve Aşağı yöntemlerinde kod gerektirerek geçiş iskelesi
Olası neden:
EF CLI komutları otomatik olarak kapanmaz ve kod dosyalarını kaydetmez. Komutu çalıştırarak değişiklikleriniz varsa EF migrations add değişikliklerinizi bulamaz.
Çözüm:
komutunu migrations remove çalıştırın, kod değişikliklerinizi kaydedin ve komutu yeniden migrations add çalıştırın.
Veritabanı güncelleştirmesi çalışırken oluşan hatalar
Mevcut verileri olan bir veritabanında şema değişiklikleri yaparken başka hatalar da almak mümkündür. Çözümleyemiyorsanız geçiş hataları alırsanız bağlantı dizesinde veritabanı adını değiştirebilir veya veritabanını silebilirsiniz. Yeni bir veritabanıyla geçirilir veri yoktur ve update-database komutunun hatasız tamamlanması çok daha olasıdır.
En basit yaklaşım, içinde veritabanını yeniden appsettings.json adlandırmaktır. 'i bir sonraki database update çalıştırmada yeni bir veritabanı oluşturulur.
SSOX'te bir veritabanını silmek için veritabanına sağ tıklayın, Sil'e tıklayın ve ardından Veritabanını Sil iletişim kutusunda Var olan bağlantıları kapat'ı seçin ve Tamam'a tıklayın.
CLI kullanarak veritabanını silmek için CLI komutunu database drop çalıştırın:
dotnet ef database drop
Örnek için SQL Server bulma hatası
Hata İletisi:
SQL Server ile bağlantı kurulmaya çalışılırken ağ ile ilişkili veya örneğe özgü bir hata oluştu. Sunucu bulunamadı veya erişilebilir değildi. Örnek adının doğru olduğunu ve uzak bağlantılara izin SQL Server yapılandırıldığından emin olun. (sağlayıcı: SQL Arabirimleri, hata: 26 - Belirtilen Sunucu/Örneği Bulma Hatası)
Çözüm:
Bağlantı dizesini kontrol edin. Veritabanı dosyasını el ile sildikten sonra yeni bir veritabanıyla başlamak için oluşturma dizesinde veritabanının adını değiştirebilirsiniz.
Kodu alma
Tamamlanan uygulamayı indirme veya görüntüleme.
Ek kaynaklar
Daha fazla bilgi EF Core için, Entity Framework Core bakın. Kitap da mevcuttur: Entity Framework Core olarak.
Web uygulaması dağıtma hakkında bilgi için bkz. Konak ve dağıtım ASP.NET Core .
Kimlik doğrulaması ve yetkilendirme gibi MVC ASP.NET Core diğer konular hakkında bilgi için bkz. ASP.NET Core’a Giriş .
Sonraki adımlar
Bu öğreticide şunları yaptınız:
- Ham SQL gerçekleştirildi
- Varlıkları iade etmek için sorgu çağrıldı
- Diğer türleri geri dönmek için sorgu çağrıldı
- Güncelleştirme sorgusu olarak adlandırılan
- Sorgular SQL incelendi
- Soyutlama katmanı oluşturuldu
- Otomatik değişiklik algılama hakkında bilgi
- Kaynak kodu EF Core geliştirme planlarını öğrenme
- Kodu basitleştirmek için dinamik LINQ kullanmayı öğrendin
Bu, Entity Framework Core MVC uygulamasında ASP.NET Core öğretici serisini tamamlar. Bu seri yeni bir veritabanıyla çalıştı; alternatif olarak, bir modeli mevcut veritabanından tersine mühendislik yapmaktır.