eitaa logo
پروژه ASP.Net Core MVC (وب و سی شارپ)
119 دنبال‌کننده
168 عکس
38 ویدیو
376 فایل
❁﷽❁ آموزش 📖 برنامه نویسی ASP.Net Core MVC (وب و سی شارپ) Admin: @alialirezapanahi برنامه نویسی برنامه نویسی سی شارپ eitaa.com/sisharpapp برنامه نویسی وب eitaa.com/aspdatnet ویراستی virasty.com/alialirezapanahi آپارات aparat.com/alialirezapanahi
مشاهده در ایتا
دانلود
پیکربندی_پایگاه_داده_در_EF_Core__از_DbContext_تا_Fluent_API_و_ف.mp3
زمان: حجم: 23.5M
پیکربندی پایگاه داده در EF Core از DBContext تا Fluent API ساخته شده از هوش مصنوعی
پروژه ASP.Net Core MVC (وب و سی شارپ)
پیکربندی پایگاه داده در EF Core از DBContext تا Fluent API ساخته شده از هوش مصنوعی
بیا با هم یه پادکست آموزشی طراحی کنیم درباره‌ی کانتکس، مدل‌بیلدر و مدل‌کریتینگ در EF Core و ASP.NET Core MVC. این پادکست می‌تونه هم برای یادگیری خودت مفید باشه، هم برای تولید محتوا در کانالت. --- 🎧 عنوان پادکست: «در دل DbContext: مدل‌سازی حرفه‌ای با ModelBuilder و OnModelCreating در ASP.NET Core MVC» --- 🎙️ مقدمه سلام! امروز می‌خوایم بریم سراغ قلب ارتباط با دیتابیس در ASP.NET Core MVC—یعنی کلاس DbContext. با هم بررسی می‌کنیم که چطور با ModelBuilder و متد OnModelCreating می‌تونیم ساختار دیتابیس رو دقیق، حرفه‌ای و قابل توسعه طراحی کنیم. --- 🧩 بخش اول: DbContext چیست؟ - کلاس مرکزی برای ارتباط با دیتابیس - شامل DbSet‌ها برای هر مدل (مثل Books, Users, Orders) - EF Core از این کلاس برای ساخت کوئری، ذخیره‌سازی و بارگذاری داده استفاده می‌کنه --- 🔹 بخش دوم: OnModelCreating و ModelBuilder ✅ OnModelCreating - متدی در DbContext که EF Core هنگام راه‌اندازی صدا می‌زنه - داخلش می‌تونی ساختار جدول‌ها، روابط، محدودیت‌ها و رفتارها رو تعریف کنی ✅ ModelBuilder - شیء ورودی به OnModelCreating - باهاش می‌تونی مدل‌ها رو پیکربندی کنی با Fluent API --- 🔧 بخش سوم: چه کارهایی می‌تونیم با ModelBuilder انجام بدیم؟ 1️⃣ تعریف کلید اصلی و ترکیبی csharp modelBuilder.Entity<Book>().HasKey(b => b.Id); 2️⃣ تعریف روابط بین جدول‌ها csharp modelBuilder.Entity<Book>() .HasOne(b => b.Author) .WithMany(a => a.Books) .HasForeignKey(b => b.AuthorId); 3️⃣ جلوگیری از حذف آیتم‌های مرتبط csharp .OnDelete(DeleteBehavior.Restrict); 4️⃣ محدودیت روی فیلدها csharp .Property(b => b.Title).HasMaxLength(200).IsRequired(); 5️⃣ مقدار پیش‌فرض csharp .Property(b => b.IsAvailable).HasDefaultValue(true); 6️⃣ فیلتر جهانی csharp .HasQueryFilter(p => p.IsActive); --- 📋 بخش چهارم: آیا ModelBuilder و OnModelCreating جدا هستند؟ - ModelBuilder فقط داخل OnModelCreating استفاده می‌شه - OnModelCreating متدی مستقل در DbContext هست - می‌تونی پیکربندی‌ها رو به کلاس‌های جداگانه منتقل کنی با ApplyConfiguration() برای نظم بیشتر --- 🎯 جمع‌بندی پادکست با استفاده از ModelBuilder در OnModelCreating می‌تونی: - ساختار دیتابیس رو دقیق کنترل کنی - روابط بین جدول‌ها رو تعریف کنی - از حذف ناخواسته داده‌های مرتبط جلوگیری کنی - محدودیت‌ها، ایندکس‌ها و فیلترهای پیش‌فرض رو تنظیم کنی - پروژه‌ت رو حرفه‌ای، امن و قابل توسعه بسازی
همش این نیست—دنیای EF Core و ASP.NET Core MVC خیلی گسترده‌تره! 😄 اون چیزی که تا حالا گفتیم مربوط به پیکربندی مدل‌ها با ModelBuilder و OnModelCreating بود، ولی کلی قابلیت دیگه هم وجود داره که مکمل این بخش‌ها هستن و پروژه‌ت رو حرفه‌ای‌تر می‌کنن. --- 🧩 چیزهای دیگر که کنار ModelBuilder و OnModelCreating وجود دارند: 🔹 ۱. Data Annotations پیکربندی مدل‌ها با استفاده از ویژگی‌های تزئینی روی کلاس‌ها: csharp [Required] [MaxLength(100)] public string Title { get; set; } 📌 ساده‌تر از Fluent API، ولی محدودتر --- 🔹 ۲. Migration و به‌روزرسانی دیتابیس - ایجاد فایل‌های مهاجرت با Add-Migration - اعمال تغییرات با Update-Database - بررسی تاریخچه تغییرات دیتابیس 📌 برای هماهنگی مدل‌ها با دیتابیس واقعی --- 🔹 ۳. Seed Data (داده اولیه) csharp modelBuilder.Entity<Category>().HasData( new Category { Id = 1, Name = "ASP.NET" }, new Category { Id = 2, Name = "EF Core" } ); 📌 برای پر کردن دیتابیس با داده‌های پیش‌فرض --- 🔹 ۴. Global Query Filters csharp modelBuilder.Entity<Product>() .HasQueryFilter(p => p.IsActive); 📌 اعمال فیلتر روی همه‌ی کوئری‌ها به‌صورت خودکار --- 🔹 ۵. Value Conversions تبدیل نوع داده‌ها هنگام ذخیره‌سازی: csharp modelBuilder.Entity<User>() .Property(u => u.IsAdmin) .HasConversion<int>(); 📌 برای تبدیل bool به int یا enum به string --- 🔹 ۶. Shadow Properties فیلدهایی که در کلاس مدل نیستن ولی در دیتابیس هستن: csharp modelBuilder.Entity<Product>() .Property<DateTime>("LastUpdated"); 📌 برای ذخیره اطلاعات سیستمی بدون تغییر مدل --- 🔹 ۷. Table Splitting ذخیره چند کلاس در یک جدول: csharp modelBuilder.Entity<Order>().ToTable("Orders"); modelBuilder.Entity<Invoice>().ToTable("Orders"); 📌 برای بهینه‌سازی ساختار دیتابیس --- 🔹 ۸. Query Types / Keyless Entities برای نمایش داده‌هایی که کلید اصلی ندارن: csharp modelBuilder.Entity<ReportView>().HasNoKey(); 📌 مناسب برای گزارش‌ها و ویوهای فقط‌خواندنی --- 🔹 ۹. Change Tracking و State Management بررسی وضعیت رکوردها: csharp context.Entry(book).State = EntityState.Modified; 📌 برای کنترل دقیق عملیات CRUD --- 🔹 ۱۰. Interceptors و Logging شنود عملیات EF Core: csharp optionsBuilder.AddInterceptors(new MyInterceptor()); 📌 برای لاگ‌گیری، امنیت، یا مانیتورینگ --- 🎯 نتیجه‌گیری پس ModelBuilder و OnModelCreating فقط بخشی از دنیای EF Core هستن. کنار اون‌ها کلی ابزار و تکنیک دیگه وجود داره که بهت کمک می‌کنن: - ساخت دیتابیس حرفه‌ای - کنترل رفتار داده‌ها - بهینه‌سازی عملکرد - تولید گزارش و داشبورد - و حتی امنیت و لاگ‌گیری ---
پروژه ASP.Net Core MVC (وب و سی شارپ)
🎯 درس جدید: تنظیم دقیق مدل‌ها با ModelBuilder در EF Core در این مرحله از پروژه مدیریت نویسنده و کتا
پاسخ بستگی داره که هدفت چی باشه—آیا فقط می‌خوای بررسی کنی که نویسنده کتاب دارد یا نه؟ یا می‌خوای اطلاعات کامل نویسنده و کتاب‌ها را واکشی کنی؟ بیایم دقیق مقایسه کنیم: --- ✅ روش اول: واکشی فقط نام اولین کتاب
csharp
var firstTitle = _context.Books
    .Where(b => b.AuthorId == id)
    .Select(b => b.Title)
    .FirstOrDefault();
🔹 هدف: فقط گرفتن نام اولین کتاب 🔹 مزایا: - سریع‌تر و سبک‌تر - فقط یک ستون (Title) واکشی می‌شود - مناسب برای بررسی ساده یا نمایش خلاصه 🔹 معایب: - اطلاعات نویسنده واکشی نمی‌شود - اگر بخواهی لیست کامل کتاب‌ها یا جزئیات بیشتر داشته باشی، کافی نیست --- ✅ روش دوم: واکشی نویسنده با لیست کتاب‌ها
csharp
var author = _context.Authors
    .Include(a => a.Books)
    .FirstOrDefault(a => a.Id == id);
🔹 هدف: گرفتن نویسنده و تمام کتاب‌هایش 🔹 مزایا: - اطلاعات کامل نویسنده و کتاب‌ها در دسترس است - مناسب برای Viewهایی که جزئیات کامل را نمایش می‌دهند - می‌توانی بررسی کنی author.Books.Any() یا لیست را نمایش دهی 🔹 معایب: - سنگین‌تر از روش اول - در دیتابیس‌های بزرگ ممکن است کندتر باشد --- ✨ نتیجه‌گیری برای دفترت | هدف | روش بهتر | دلیل | |------|-----------|--------| | فقط بررسی یا نمایش یک کتاب | firstTitle | سبک و سریع | | نمایش نویسنده و همه کتاب‌ها | author + Include | کامل و دقیق | | پروژه‌های بزرگ با داده زیاد | firstTitle | بهینه‌تر | | فرم‌های جزئیات یا حذف | author + Include | چون نیاز به بررسی Books.Any() داری |
پروژه ASP.Net Core MVC (وب و سی شارپ)
🎯 درس جدید: تنظیم دقیق مدل‌ها با ModelBuilder در EF Core در این مرحله از پروژه مدیریت نویسنده و کتا
اگر بخوای همون داده‌ها رو با Select بنویسی، یعنی به‌جای واکشی کامل شیء Author، فقط فیلدهای خاصی رو واکشی کنی—و این باعث می‌شه کد سبک‌تر و سریع‌تر بشه، مخصوصاً در دیتابیس‌های بزرگ. --- ✅ تبدیل Include + FirstOrDefault به Select کد اصلی:
csharp
var author = _context.Authors
    .Include(a => a.Books)
    .FirstOrDefault(a => a.Id == id);
🔹 این کد کل شیء Author و لیست Books رو واکشی می‌کنه 🔹 اگر فقط بعضی فیلدها رو بخوای، می‌تونی از Select استفاده کنی: --- 🎯 نسخه با Select
csharp
var authorData = _context.Authors
    .Where(a => a.Id == id)
    .Select(a => new
    {
        a.Id,
        a.FullName,
        BookTitles = a.Books.Select(b => b.Title).ToList()
    })
    .FirstOrDefault();
🔹 این کد فقط Id, FullName و لیست Title کتاب‌ها رو واکشی می‌کنه 🔹 خروجی یک شیء بی‌نام (anonymous type) هست—not کلاس Author --- 🧠 تفاوت‌ها | مورد | Include + FirstOrDefault | Select + FirstOrDefault | |------|-----------------------------|----------------------------| | نوع خروجی | Author | شیء بی‌نام | | حجم داده | زیادتر | سبک‌تر | | انعطاف در انتخاب فیلدها | کم | زیاد | | مناسب برای View | بله | بله، اگر فقط فیلدهای خاص بخواهی | | مناسب برای حذف یا ویرایش | بهتر است از Author استفاده شود | چون نیاز به شیء کامل داری | --- ✨ نتیجه‌گیری برای دفترت | هدف | روش بهتر | دلیل | |------|-----------|--------| | نمایش خلاصه اطلاعات | Select | سبک‌تر و سریع‌تر | | عملیات حذف یا ویرایش | Include + FirstOrDefault | نیاز به شیء کامل | | واکشی فقط نام کتاب‌ها | Select(a => new { ... }) | دقیق و بهینه |
پروژه ASP.Net Core MVC (وب و سی شارپ)
🎯 درس جدید: تنظیم دقیق مدل‌ها با ModelBuilder در EF Core در این مرحله از پروژه مدیریت نویسنده و کتا
var firstTitle = _context.Books .Where(b => b.AuthorId == id) .Select(b => b.Title) .FirstOrDefault(); دقیقاً همین کد به‌درستی کار می‌کند برای اینکه بفهمی آیا نویسنده کتاب دارد یا نه 👌 بیایم دقیق بررسی کنیم که چرا این روش مؤثر و بهینه است: --- ✅ کد بررسی داشتن کتاب با FirstOrDefault
csharp
var firstTitle = _context.Books
    .Where(b => b.AuthorId == id)
    .Select(b => b.Title)
    .FirstOrDefault();
🔹 این کد می‌ره سراغ جدول Books 🔹 فقط کتاب‌هایی رو بررسی می‌کنه که AuthorId برابر با id باشه 🔹 فقط ستون Title رو واکشی می‌کنه—not کل شیء کتاب 🔹 فقط اولین عنوان کتاب رو می‌گیره، یا null اگر هیچ کتابی نباشه --- 🎯 بررسی شرط
csharp
if (firstTitle != null)
{
    // نویسنده کتاب دارد
}
else
{
    // نویسنده کتاب ندارد
}
✅ این شرط کاملاً درست و سبک هست ✅ مناسب برای پروژه‌هایی که فقط می‌خوای بررسی کنی نویسنده کتاب دارد یا نه ✅ سریع‌تر از Include و واکشی کل لیست کتاب‌ها --- ✨ مزایای این روش | مزیت | توضیح | |------|-------| | سبک و سریع | فقط یک مقدار واکشی می‌شود—not کل لیست | | بدون نیاز به Include | چون فقط از جدول Books استفاده می‌کنی | | مناسب برای شرط حذف | چون فقط بررسی می‌کنی که کتاب دارد یا نه | | قابل استفاده در پروژه‌های بزرگ | چون فشار کمتری به دیتابیس وارد می‌کند
پروژه ASP.Net Core MVC (وب و سی شارپ)
🎯 درس جدید: تنظیم دقیق مدل‌ها با ModelBuilder در EF Core در این مرحله از پروژه مدیریت نویسنده و کتا
وقتی از ModelBuilder استفاده می‌کنی تا محدودیت‌هایی مثل ایندکس یکتا برای کتاب تکراری یا ممنوعیت حذف نویسنده دارای کتاب تعریف کنی، اگر کاربر خلاف این محدودیت‌ها عمل کنه، خطای SQL یا EF Core رخ می‌ده. حالا باید در اکشن‌های کنترلر، این خطاها رو مدیریت (catch) کنی تا برنامه کرش نکنه و پیام مناسب به کاربر نمایش داده بشه. --- ✅ 1. جلوگیری از ثبت کتاب تکراری با مدیریت خطای SQL 📍 فرض: در ModelBuilder نوشتی:
csharp
modelBuilder.Entity<Book>()
    .HasIndex(b => new { b.Title, b.AuthorId })
    .IsUnique();
📍 حالا در اکشن Create یا Edit باید خطای دیتابیس رو مدیریت کنی:
csharp
try
{
    _context.Books.Add(book);
    _context.SaveChanges();
    return RedirectToAction("Index");
}
catch (DbUpdateException ex)
{
    // بررسی اینکه خطا مربوط به ایندکس یکتا بوده
    if (ex.InnerException?.Message.Contains("IXBooksTitle_AuthorId") == true)
    {
        ModelState.AddModelError("Title", "این نویسنده قبلاً کتابی با این عنوان دارد.");
    }
    else
    {
        ModelState.AddModelError("", "خطایی در ثبت کتاب رخ داد.");
    }

    return View(book);
}
🔹 این کد خطای DbUpdateException رو مدیریت می‌کنه 🔹 اگر خطا مربوط به ایندکس یکتا باشه، پیام مناسب نمایش داده می‌شه 🔹 اگر خطای دیگری باشه، پیام عمومی نمایش داده می‌شه --- ✅ 2. جلوگیری از حذف نویسنده دارای کتاب با مدیریت خطای SQL 📍 فرض: در ModelBuilder نوشتی:
csharp
modelBuilder.Entity<Book>()
    .HasOne(b => b.Author)
    .WithMany(a => a.Books)
    .HasForeignKey(b => b.AuthorId)
    .OnDelete(DeleteBehavior.Restrict);
📍 حالا در اکشن DeleteConfirmed باید خطا را مدیریت کنی:
csharp
try
{
    var author = _context.Authors.Find(id);
    _context.Authors.Remove(author);
    _context.SaveChanges();
    return RedirectToAction("Index");
}
catch (DbUpdateException ex)
{
    TempData["DeleteError"] = "نمی‌توان نویسنده‌ای که کتاب دارد را حذف کرد.";
    return RedirectToAction("Index");
}
🔹 اگر نویسنده کتاب داشته باشد، حذف ممنوع است و EF Core خطا می‌دهد 🔹 با catch این خطا را می‌گیری و پیام مناسب به کاربر نمایش می‌دهی 🔹 از TempData برای نمایش پیام در صفحه لیست استفاده می‌کنی --- ✨ نکات حرفه‌ای - همیشه قبل از SaveChanges() از try-catch استفاده کن وقتی محدودیت دیتابیس داری - می‌تونی از ex.InnerException.Message برای تشخیص نوع خطا استفاده کنی - بهتره قبل از رسیدن به خطای دیتابیس، با Any() یا Count() بررسی کنی تا کاربر تجربه بهتری داشته باشه
پروژه ASP.Net Core MVC (وب و سی شارپ)
🎯 درس جدید: تنظیم دقیق مدل‌ها با ModelBuilder در EF Core در این مرحله از پروژه مدیریت نویسنده و کتا
الان می‌خوای بدونی چرا این کوئری‌ها با اینکه شبیه هم هستن، هرکدوم ساختار متفاوتی دارن و چه زمانی باید از هرکدوم استفاده کرد. بیایم با دسته‌بندی، مثال، و توضیح کامل همه کوئری‌ها رو بررسی کنیم تا هیچ ابهامی باقی نمونه. --- 🧠 دسته‌بندی کلی کوئری‌ها تو ۷ کوئری دادی که می‌تونیم به ۳ دسته تقسیم کنیم: | دسته | هدف | شروع از | |------|------|----------| | ➊ واکشی کتاب‌ها با نام نویسنده | نمایش لیست کتاب‌ها | Books | | ➋ واکشی نویسنده‌ها با تعداد یا لیست کتاب‌ها | گزارش‌گیری نویسنده‌محور | Authors | | ➌ واکشی اطلاعات خاص بر اساس authorId | فیلتر شده بر اساس نویسنده | ترکیبی | --- 🔍 بررسی دقیق هر کوئری --- ✅ ➊ کوئری اول: کتاب‌ها با نام نویسنده (تو در تو)
csharp
var books = query
    .Select(b => new
    {
        b.Id,
        b.Title,
        b.IsAvailable,
        AuthorName = _context.Authors
            .Where(a => a.Id == b.AuthorId)
            .Select(a => a.FullName)
            .FirstOrDefault()
    })
    .ToList();
🔹 ویژگی‌ها: - از Books شروع می‌کنی - برای هر کتاب، با AuthorId می‌ری سراغ جدول Authors - Select تو در تو باعث می‌شه EF پشت‌صحنه JOIN بزنه - مناسب برای لیست کتاب‌ها با نام نویسنده 🔸 نکته مهم: اگر b.Author به‌صورت Navigation Property تعریف شده باشه، بهتره از b.Author.FullName استفاده کنی (مثل کوئری ➐) --- ✅ ➋ کوئری دوم: نویسنده‌ها با تعداد کتاب‌ها
csharp
var authors = _context.Authors
    .Select(a => new
    {
        a.Id,
        a.FullName,
        BookCount = _context.Books.Count(b => b.AuthorId == a.Id)
    })
    .ToList();
🔹 ویژگی‌ها: - از Authors شروع می‌کنی - برای هر نویسنده، تعداد کتاب‌هاش رو با Count محاسبه می‌کنی - مناسب برای داشبورد آماری یا گزارش‌گیری --- ✅ ➌ کوئری سوم و چهارم: واکشی اطلاعات خاص بر اساس authorId
csharp
var authorName = _context.Authors
    .Where(a => a.Id == authorId)
    .Select(a => a.FullName)
    .FirstOrDefault();

var books = _context.Books
    .Where(b => b.AuthorId == authorId)
    .Select(b => new
    {
        b.Id,
        b.Title,
        b.IsAvailable
    })
    .ToList();
🔹 ویژگی‌ها: - جدا جدا اطلاعات نویسنده و کتاب‌هاش رو می‌گیری - مناسب برای صفحه جزئیات نویسنده یا فیلتر شده بر اساس انتخاب کاربر --- ✅ ➍ کوئری پنجم: نویسنده‌ها با تعداد و لیست کتاب‌های اخیر
csharp
var authors = _context.Authors
    .Select(a => new
    {
        a.Id,
        a.FullName,
        BookCount = _context.Books.Count(b => b.AuthorId == a.Id),
        Books = _context.Books
            .Where(b => b.AuthorId == a.Id)
            .OrderByDescending(b => b.Id)
            .Take(6)
            .Select(b => new
            {
                b.Id,
                b.Title,
                b.IsAvailable
            }).ToList()
    })
    .ToList();
🔹 ویژگی‌ها: - ترکیب Count و Select تو در تو - برای هر نویسنده، ۶ کتاب آخرش رو می‌گیری - مناسب برای صفحه نویسنده با خلاصه آثار 🔸 نکته مهم: چون از _context.Books جدا استفاده می‌کنی، EF ممکنه کوئری‌های جداگانه بزنه (وابسته به تنظیمات) --- ✅ ➎ کوئری ششم: نویسنده‌ها با لیست عنوان کتاب‌ها (با Navigation)
csharp
var authors = _context.Authors
    .Select(a => new
    {
        a.FullName,
        Books = a.Books.Select(b => b.Title).ToList()
    })
    .ToList();
🔹 ویژگی‌ها: - از Authors شروع می‌کنی - از a.Books استفاده می‌کنی که باید Navigation Property باشه - ساده و بهینه، مناسب برای نمایش آثار نویسنده 🔸 نکته مهم: اگر Books در مدل Author تعریف نشده باشه، این کد خطا می‌ده --- ✅ ➏ کوئری هفتم: کتاب‌ها با نام نویسنده (با Navigation)
csharp
var books = _context.Books
    .Select(b => new
    {
        b.Title,
        b.IsAvailable,
        AuthorName = b.Author.FullName
    })
    .ToList();
🔹 ویژگی‌ها: - ساده‌ترین و بهینه‌ترین روش - از b.Author.FullName استفاده می‌کنی که باید Navigation Property باشه - مناسب برای لیست کتاب‌ها با اطلاعات نویسنده --- 🧩 تفاوت‌های کلیدی بین کوئری‌ها
پروژه ASP.Net Core MVC (وب و سی شارپ)
🎯 درس جدید: تنظیم دقیق مدل‌ها با ModelBuilder در EF Core در این مرحله از پروژه مدیریت نویسنده و کتا
| کوئری | شروع از | نوع Select | نیاز به Navigation | کاربرد | |-------|----------|---------------|---------------------|---------| | ➊ | Books | تو در تو | نه | لیست کتاب‌ها با نویسنده | | ➋ | Authors | Count | نه | تعداد کتاب‌ها | | ➌ | ترکیبی | جداگانه | نه | فیلتر شده بر اساس نویسنده | | ➍ | Authors | Count + Select تو در تو | نه | لیست محدود کتاب‌ها | | ➎ | Authors | Select ساده | بله | لیست عنوان کتاب‌ها | | ➏ | Books | Select ساده | بله | لیست کتاب‌ها با نویسنده | --- 🎯 جمله‌های یادسپاری برای جلوگیری از اشتباه - اگر از جدول شروع می‌کنی، فقط به فیلدهای همون جدول مستقیم دسترسی داری - اگر می‌خوای اطلاعات جدول مرتبط رو بیاری، باید از Select تو در تو یا Navigation استفاده کنی - اگر از ToList() زودتر استفاده کنی، باید Include بزنی تا اطلاعات مرتبط لود بشه - اگر Navigation Property نداری، نمی‌تونی از b.Author.FullName استفاده کنی
پروژه ASP.Net Core MVC (وب و سی شارپ)
ویرایش پروژه
این سه بخش از پروژه BookSelect که گفتی، هرکدوم هدف مشخصی دارن و با هم هماهنگ هستن. بیایم دقیق و خلاصه توضیح بدیم: --- ## ✅ 1. فیلتر نمایش ندادن نویسنده‌های بدون کتاب در صفحه اصلی در کنترلر
Index
از این شرط استفاده شده:
.Where(a => _context.Books.Any(b => b.AuthorId == a.Id))
این یعنی فقط نویسنده‌هایی واکشی می‌شن که حداقل یک کتاب دارن. ✅ باعث می‌شه نویسنده‌های بدون کتاب اصلاً در لیست صفحه اصلی دیده نشن ✅ تعداد صفحات هم بر اساس همین فیلتر محاسبه می‌شه --- ## ✅ 2. غیرفعال کردن دکمه "کتاب‌های بیشتر" برای نویسنده‌های بدون کتاب در View از شرط
BookCount > 0
استفاده می‌کنی:
@if (author.BookCount > 0)
{
    <a href="..." class="btn btn-outline-primary">کتاب‌های بیشتر</a>
}
else
{
    <button class="btn btn-outline-secondary" disabled>کتابی ندارد</button>
}
✅ وقتی نویسنده کتاب نداره، دکمه لینک‌دار نمایش داده نمی‌شه ✅ به‌جاش یه دکمه غیرفعال با پیام مناسب نشون داده می‌شه ✅ تجربه کاربری بهتر و بدون خطا --- ## ✅ 3. استفاده از `AsNoTracking()` در حذف نویسنده در اکشن
DeleteConfirmed
از این خط استفاده شده:
var author = _context.Authors
    .AsNoTracking()
    .Include(a => a.Books)
    .FirstOrDefault(a => a.Id == id);
AsNoTracking()
یعنی EF Core داده‌ها رو فقط برای خواندن واکشی می‌کنه ✅ چون قرار نیست
author
تغییر داده بشه (فقط بررسی و حذف می‌شه)، ردیابی لازم نیست ✅ باعث افزایش سرعت و کاهش مصرف حافظه می‌شه ✅ مناسب برای عملیات‌هایی مثل حذف، که فقط بررسی و تصمیم‌گیری انجام می‌شه --- ## 🎯 جمع‌بندی: | بخش | هدف | نتیجه | |-----|------|--------| | فیلتر نویسنده‌ها | حذف نویسنده‌های بدون کتاب از لیست | نمایش دقیق و مرتبط | | دکمه کتاب بیشتر | کنترل نمایش دکمه بر اساس تعداد کتاب | تجربه کاربری بهتر | | AsNoTracking | واکشی سبک و سریع برای حذف | بهینه‌سازی عملکرد |