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
مشاهده در ایتا
دانلود
پروژه ASP.Net Core MVC (وب و سی شارپ)
بهینه سازی کار با داده در ASP.Net Core MVC ساخته شده از هوش مصنوعی نکته: شاید پادکست تکراری باشد و
بیا این رو به شکل یک اسکریپت پادکست آموزشی آماده کنیم که هم شنیدنی باشه، هم پر از مثال عملی. این متن رو می‌تونی هم برای ضبط صدا استفاده کنی، هم بعداً به عنوان یادداشت آموزشی نگه داری. --- 🎧 عنوان پادکست: «سه روش بارگذاری داده در EF Core + Select برای لیست کردن آیتم‌ها + صفحه‌بندی در ASP.NET Core MVC» --- 🎙️سلام امروز می‌خوایم با هم سه روش بارگذاری داده در EF Core رو یاد بگیریم، بعد با Select فقط فیلدهای لازم رو بگیریم، و در نهایت با صفحه‌بندی (Pagination) حجم داده رو کنترل کنیم تا پروژه‌هامون سریع‌تر و بهینه‌تر بشه. --- 🧩 بخش اول: سه روش بارگذاری داده در EF Core 1️⃣ Eager Loading – بارگذاری پیش‌گیرانه - با Include() داده‌های مرتبط رو هم‌زمان با داده اصلی می‌آریم. - مثال:
csharp
var products = _context.Products
    .Include(p => p.Category)
    .ToList();
📌 مزیت: فقط یک کوئری به دیتابیس 📌 عیب: ممکنه داده زیادی بیاد که لازم نداشته باشیم --- 2️⃣ Lazy Loading – بارگذاری تنبل - داده‌های مرتبط فقط وقتی لود می‌شن که بهشون دسترسی پیدا کنیم. - نیاز به virtual و فعال‌سازی UseLazyLoadingProxies():
csharp
var product = _context.Products.First();
var categoryName = product.Category.Name; // اینجا کوئری جدا اجرا میشه
📌 مزیت: فقط داده لازم لود میشه 📌 عیب: خطر N+1 Query --- 3️⃣ Explicit Loading – بارگذاری صریح - خودمون به صورت دستی و در زمان دلخواه داده مرتبط رو لود می‌کنیم:
csharp
var category = _context.Categories.First();
_context.Entry(category)
    .Collection(c => c.Products)
    .Load();
📌 مزیت: کنترل کامل روی زمان و نوع بارگذاری 📌 عیب: نیاز به کدنویسی بیشتر --- 🧩 بخش دوم: استفاده از Select برای لیست کردن آیتم‌ها گاهی همه‌ی ستون‌ها رو لازم نداریم. با Select فقط فیلدهای موردنیاز رو می‌گیریم:
csharp
var productList = _context.Products
    .Select(p => new { p.Title, p.Price })
    .ToList();
📌 مزیت: حجم داده کمتر → سرعت بیشتر --- 🧩 بخش سوم: صفحه‌بندی برای کنترل حجم داده فرمول اصلی:
csharp
int pageSize = 10;
int pageNumber = 2;
int skipCount = (pageNumber - 1) * pageSize;
کوئری:
csharp
var products = _context.Products
    .AsNoTracking()
    .Include(p => p.Category)
    .OrderBy(p => p.Title)
    .Skip(skipCount)
    .Take(pageSize)
    .ToList();
📌 اینطوری مثلاً صفحه دوم رو می‌گیریم: آیتم‌های ۱۱ تا ۲۰. --- 🧠 نکات پایانی: - همیشه قبل از Skip() مرتب‌سازی (OrderBy) انجام بده - برای داده‌های فقط خواندنی از AsNoTracking() استفاده کن - با ToQueryString() می‌تونی SQL نهایی رو ببینی و بهینه کنی - انتخاب روش بارگذاری بستگی به نیاز پروژه و حجم داده داره --- 🎯 جمع‌بندی پادکست: با شناخت سه روش بارگذاری داده، استفاده از Select برای کم کردن حجم، و پیاده‌سازی صفحه‌بندی، می‌تونی پروژه‌های ASP.NET Core MVC رو سریع‌تر و بهینه‌تر بسازی.
پروژه ASP.Net Core MVC (وب و سی شارپ)
بهینه سازی کار با داده در ASP.Net Core MVC ساخته شده از هوش مصنوعی نکته: شاید پادکست تکراری باشد و
در EF Core وقتی از Select استفاده می‌کنی، می‌تونی هم داده‌های اصلی و هم داده‌های مرتبط (Navigation Properties) رو انتخاب کنی—و حتی روی همون نتیجه صفحه‌بندی (Skip و Take) انجام بدی. --- 🧩 ایده کلی Select بهت اجازه می‌ده فقط فیلدهایی که لازم داری رو از چند جدول مرتبط بگیری، بدون اینکه کل موجودیت‌ها رو لود کنی. این کار باعث می‌شه حجم داده کمتر بشه و سرعت بیشتر. --- 🔹 مثال: لیست کردن همه آیتم‌های مرتبط فرض کن دو جدول داری: Product و Category (یک محصول یک دسته‌بندی دارد).
csharp
var products = _context.Products
    .Select(p => new 
    {
        p.Title,
        p.Price,
        CategoryName = p.Category.Name
    })
    .ToList();
📌 اینجا EF Core خودش Join می‌زنه و اسم دسته‌بندی رو هم میاره، بدون نیاز به Include(). --- 🔹 مثال: صفحه‌بندی روی داده‌های انتخاب‌شده
csharp
int pageSize = 10;
int pageNumber = 2;

var products = _context.Products
    .Where(p => p.IsActive)
    .OrderBy(p => p.Title)
    .Select(p => new 
    {
        p.Title,
        p.Price,
        CategoryName = p.Category.Name
    })
    .Skip((pageNumber - 1) * pageSize)
    .Take(pageSize)
    .ToList();
✅ این کوئری: - فقط فیلدهای لازم رو میاره (Title, Price, CategoryName) - صفحه‌بندی رو روی همون داده‌ها انجام می‌ده - بهینه‌تر از Include هست وقتی کل موجودیت رو لازم نداری --- 🧠 نکات حرفه‌ای - وقتی فقط چند فیلد لازم داری، Select بهتر از Include هست چون حجم داده کمتره - Select می‌تونه چند سطح رابطه رو هم بیاره، مثلاً:
csharp
  .Select(o => new {
      o.Id,
      o.Customer.Name,
      City = o.Customer.Address.City
  })
  
- صفحه‌بندی (Skip/Take) رو می‌تونی بعد از Select یا قبلش بزنی، ولی معمولاً بعد از OrderBy و قبل از ToList() میاد
وقتی می‌خوای داده‌ای رو از دیتابیس بارگذاری کنی (مثلاً لیست کتاب‌ها یا محصولات)، چند مرحله مهم وجود داره که هر کد حرفه‌ای باید رعایت کنه. این مراحل نه‌تنها باعث می‌شن کدت بهینه باشه، بلکه قابل توسعه، قابل تست و قابل فهم هم می‌شه. بذار این مراحل رو خیلی واضح و قابل استفاده برات لیست کنم، طوری که همیشه بتونی بهش رجوع کنی و ترتیب اجرای کوئری‌ها در EF Core رو اصولی یاد بگیری. --- ✅ مراحل استاندارد بارگذاری داده در EF Core 1️⃣ AsNoTracking() - کاربرد: حذف ردیابی تغییرات توسط EF - هدف: سبک‌سازی کوئری‌های فقط خواندنی - مثال:
csharp
  context.Books.AsNoTracking()
  
--- 2️⃣ Where() - کاربرد: فیلتر کردن داده‌ها بر اساس شرط - هدف: حذف رکوردهای غیرضروری - مثال:
csharp
  .Where(b => b.IsAvailable == true)
  
--- 3️⃣ جستجو (Search) - کاربرد: جستجو در متن یا فیلدهای خاص - هدف: پیدا کردن رکوردهای مرتبط با عبارت کاربر - مثال:
csharp
  .Where(b => b.Title.Contains(search) || b.Author.FullName.Contains(search))
  
--- 4️⃣ OrderBy() / OrderByDescending() - کاربرد: مرتب‌سازی داده‌ها - هدف: تعیین ترتیب نمایش در لیست - مثال:
csharp
  .OrderBy(b => b.Title)
  
--- 5️⃣ Skip() و Take() - کاربرد: صفحه‌بندی داده‌ها - هدف: گرفتن فقط رکوردهای صفحه فعلی - مثال:
csharp
  .Skip((page - 1) * pageSize).Take(pageSize)
  
--- 6️⃣ Select() - کاربرد: انتخاب فقط فیلدهای مورد نیاز - هدف: کاهش حجم خروجی و کنترل نمایش - مثال:
csharp
  .Select(b => new { b.Id, b.Title, b.IsAvailable })
  
--- 7️⃣ ToList() یا ToListAsync() - کاربرد: اجرای کوئری و گرفتن داده‌ها - هدف: انتقال داده‌ها به حافظه برنامه - مثال:
csharp
  .ToList()
  
--- 8️⃣ ارسال به View - کاربرد: نمایش داده‌ها در Razor یا API - هدف: ارائه خروجی به کاربر - مثال:
csharp
  return View(books);
  
--- 📌ترتیب استاندارد نوشتن کوئری در EF Core
csharp
var query = context.TableName
    .AsNoTracking()                         
// 1️⃣ سبک‌سازی
    .Where(...)                             
// 2️⃣ فیلتر
    .Where(searchCondition)               
// 3️⃣ جستجو
    .OrderBy(...)                          
// 4️⃣ مرتب‌سازی
    .Skip((page - 1) * pageSize)            
// 5️⃣ صفحه‌بندی
    .Take(pageSize)                        
// 6️⃣ محدودسازی
    .Select(x => new { ... })               
// 7️⃣ انتخاب فیلدها
    .ToList();                             
// 8️⃣ اجرا
✅ اکشن Index برای پروژه کتابخانه (نسخه آموزشی و مرحله‌به‌مرحله)
csharp
public IActionResult Index(int page = 1, int pageSize = 10, string search = "", string statusFilter = "", string sort = "")
{
    // 1️⃣ شروع کوئری با سبک‌سازی
    var query = _context.Books
        .AsNoTracking();

    // 2️⃣ فیلتر وضعیت کتاب (موجود یا فروخته‌شده)
    if (statusFilter == "available")
        query = query.Where(b => b.IsAvailable == true);
    else if (statusFilter == "sold")
        query = query.Where(b => b.IsAvailable == false);

    // 3️⃣ جستجو در عنوان یا نام نویسنده
    if (!string.IsNullOrEmpty(search))
        query = query.Where(b => b.Title.Contains(search) || b.Author.FullName.Contains(search));

    // 4️⃣ مرتب‌سازی بر اساس فیلد انتخاب‌شده
    switch (sort)
    {
        case "title":
            query = query.OrderBy(b => b.Title);
            break;
        case "status":
            query = query.OrderByDescending(b => b.IsAvailable);
            break;
        default:
            query = query.OrderBy(b => b.Id); // مرتب‌سازی پیش‌فرض
            break;
    }

    // 5️⃣ محاسبه تعداد کل رکوردها برای صفحه‌بندی
    int totalCount = query.Count();
    int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

    // 6️⃣ اعمال صفحه‌بندی
    query = query
        .Skip((page - 1) * pageSize)
        .Take(pageSize);

    // 7️⃣ انتخاب فیلدهای مورد نیاز
    var books = query
        .Select(b => new
        {
            b.Id,
            b.Title,
            b.IsAvailable,
            AuthorName = b.Author.FullName
        })
        .ToList();

    // 8️⃣ ارسال داده‌ها به View
    ViewBag.CurrentPage = page;
    ViewBag.TotalPages = totalPages;
    ViewBag.TotalCount = totalCount;
    ViewBag.PageSize = pageSize;
    ViewBag.Search = search;
    ViewBag.StatusFilter = statusFilter;
    ViewBag.Sort = sort;

    return View(books);
}
--- 🎯 ویژگی‌های این اکشن | مرحله | توضیح | |-------|--------| ۱ـ| AsNoTracking() | سبک‌سازی کوئری فقط خواندنی | ۲ـ| Where() | فیلتر وضعیت و جستجو | ۳ـ| switch | مرتب‌سازی بر اساس انتخاب کاربر | ۴ـ| Count() | محاسبه تعداد کل رکوردها | ۵ـ| Skip/Take | صفحه‌بندی واقعی | ۶ـ| Select() | خروجی سبک و قابل کنترل | ۷ـ| ViewBag | ارسال اطلاعات به View برای نمایش صفحه‌بندی و فیلترها 🧩 بخش‌های قابل حذف یا اختیاری در اکشن Index | بخش | کاربرد | آیا می‌تونی حذفش کنی؟ | |------|--------|------------------------| ۱ـ| AsNoTracking() | سبک‌سازی کوئری فقط خواندنی | ✅ اگر نیاز به ویرایش نداری، بهتره باشه | ۲ـ| فیلتر statusFilter | نمایش فقط کتاب‌های موجود یا فروخته‌شده | ✅ اگر همه کتاب‌ها رو می‌خوای، می‌تونی حذفش کنی | ۳ـ| جستجو search | پیدا کردن کتاب یا نویسنده با متن واردشده | ✅ اگر صفحه‌ات جستجو نداره، حذفش مشکلی نداره | ۴ـ| مرتب‌سازی sort | نمایش بر اساس عنوان یا وضعیت یا تاریخ | ✅ اگر ترتیب خاصی نمی‌خوای، می‌تونی حذفش کنی یا فقط یه OrderBy ساده بذاری | ۵ـ| صفحه‌بندی Skip/Take | نمایش فقط بخشی از داده‌ها در هر صفحه | ✅ اگر تعداد داده‌ها کم باشه، می‌تونی حذفش کنی و همه رو نشون بدی | ۶ـ| Select() | انتخاب فیلدهای مورد نیاز | ✅ اگر کل مدل رو می‌خوای، می‌تونی حذفش کنی و فقط ToList() بزنی | ۷ـ| ViewBag | ارسال داده‌ها به View برای نمایش فیلتر و صفحه‌بندی | ✅ اگر View ساده‌ست و این اطلاعات رو نمی‌خوای، حذفش مشکلی نداره --- 🎯 مثال ساده‌شده بدون فیلتر و صفحه‌بندی
csharp
var books = _context.Books
    .AsNoTracking()
    .OrderBy(b => b.Title)
    .Select(b => new
    {
        b.Id,
        b.Title,
        AuthorName = b.Author.FullName
    })
    .ToList();

return View(books);
✅ این نسخه برای لیست ساده کتاب‌ها بدون جستجو، فیلتر، یا صفحه‌بندی مناسبه
پروژه ASP.Net Core MVC (وب و سی شارپ)
صفر تا صد بهینه سازی کوئری در EF Core ساخته شده از هوش مصنوعی
چرا ترتیب مراحل کوئری در EF Core مهمه، باید بدونی که این ترتیب فقط برای زیبایی نیست—بلکه مستقیماً روی عملکرد، بهینه‌سازی، امنیت و خوانایی کد تأثیر می‌ذاره. بیا با هم یه پادکست آموزشی طراحی کنیم که هم شنیدنی باشه، هم کاربردی، و هم پر از مثال واقعی. --- 🎧 عنوان پادکست: «چرا ترتیب مراحل کوئری در EF Core مهمه؟ از AsNoTracking تا ToList» --- 🎙️ امروز می‌خوایم درباره‌ی یکی از مهم‌ترین اصول EF Core صحبت کنیم: ترتیب نوشتن کوئری‌ها. شاید فکر کنی ترتیب مهم نیست، ولی در واقع این ترتیب می‌تونه تفاوت بین یه کوئری سریع و یه کوئری کند باشه. پس با من همراه باش تا مرحله‌به‌مرحله بررسی کنیم. --- 🧩 مرحله 1: AsNoTracking() – سبک‌سازی از ابتدا وقتی می‌دونی داده فقط برای نمایش هست و قرار نیست تغییرش بدی، بهتره از همون اول بگی EF Core ردیابی نکنه. اگر بذاری آخر کوئری، EF از قبل ردیابی کرده و دیگه فایده‌ای نداره. 📌 پس باید اول بیاد تا کل کوئری سبک بشه. --- 🧩 مرحله 2 و 3: Where() و جستجو – حذف داده‌های اضافی قبل از هر چیز اگه اول Include یا Select بزنی و بعد Where، ممکنه کلی داده بیاد که اصلاً لازم نداری. مثل اینه که اول همه کتاب‌ها رو بیاری، بعد بگی فقط اونایی که موجودن رو نگه دار. 📌 پس اول فیلتر کن، بعد ادامه بده. --- 🧩 مرحله 4: OrderBy() – مرتب‌سازی قبل از صفحه‌بندی اگه قبل از Skip مرتب‌سازی نکنی، صفحه‌بندی بی‌معنی می‌شه. چون ترتیب مشخص نیست و هر بار داده‌ها جابه‌جا می‌شن. 📌 پس اول مرتب کن، بعد صفحه‌بندی کن. --- 🧩 مرحله 5 و 6: Skip() و Take() – کنترل حجم داده اینجا مشخص می‌کنی چند رکورد رد بشه و چند تا گرفته بشه. اگه اینو بعد از ToList() بزنی، کل داده‌ها لود می‌شن و فقط در حافظه فیلتر می‌شن—که خیلی سنگینه. 📌 پس قبل از ToList() باید باشه تا در سطح دیتابیس اجرا بشه. --- 🧩 مرحله 7: Select() – فقط فیلدهای لازم اگه کل موجودیت رو بیاری (Product یا Book) ولی فقط Title و Price رو لازم داشته باشی، داری حافظه رو بی‌خود پر می‌کنی. با Select فقط اون چیزی که لازم داری رو می‌گیری. 📌 بهتره بعد از فیلتر و صفحه‌بندی باشه، چون روی داده‌های نهایی اعمال می‌شه. --- 🧩 مرحله 8: ToList() – اجرای نهایی تا اینجا فقط کوئری ساخته شده. با ToList() یا ToListAsync() کوئری اجرا می‌شه و داده‌ها وارد حافظه می‌شن. اگه زودتر بزنی، همه چیز در حافظه انجام می‌شه و بهینه نیست. 📌 پس همیشه آخر باشه. --- 🎯 جمع‌بندی پادکست ترتیب مراحل کوئری در EF Core فقط یه توصیه نیست—یه اصل مهمه برای: - بهینه‌سازی عملکرد - کاهش مصرف حافظه - جلوگیری از بارگذاری غیرضروری - افزایش خوانایی و تست‌پذیری کد
✅ کوئری کامل و بهینه برای پروژه کتابخانه با همه ویژگی‌هایی که گفتی
csharp
var query = _context.Books
    .AsNoTracking() // 1️⃣ سبک‌سازی کوئری فقط خواندنی

    // 2️⃣ فیلتر وضعیت کتاب (موجود یا فروخته‌شده)
    .Where(b => statusFilter == "available" ? b.IsAvailable :
                statusFilter == "sold" ? !b.IsAvailable : true)

    // 3️⃣ جستجو در عنوان کتاب یا نام نویسنده
    .Where(b => string.IsNullOrEmpty(search) ||
                b.Title.Contains(search) ||
                b.Author.FullName.Contains(search))

    // 4️⃣ مرتب‌سازی بر اساس تاریخ ثبت (جدیدترین یا قدیمی‌ترین)
    .OrderByDescending(b => sort == "new" ? b.Id : 0)
    .ThenBy(b => sort == "old" ? b.Id : 0)

    // 5️⃣ صفحه‌بندی بر اساس تعداد کل رکوردها و صفحه فعلی
    .Skip((page - 1) * pageSize)
    .Take(pageSize)

    // 6️⃣ انتخاب فیلدهای مورد نیاز برای نمایش
    .Select(b => new
    {
        b.Id,
        b.Title,
        b.IsAvailable,
        AuthorName = b.Author.FullName
    })

    // 7️⃣ اجرای کوئری و گرفتن داده‌ها
    .ToList();
🔍 تفاوت‌های اصلی بین دو روش | تفاوت | روش اول (if و switch) | روش دوم (شرط داخل Where و OrderBy) | |-------|-----------------------------|----------------------------------------| | سبک نوشتن | مرحله‌مرحله با شرط‌های جدا | همه‌چیز در یک زنجیره‌ی متصل | | خوانایی | ✅ واضح‌تر برای مبتدی‌ها | کمی فشرده‌تر ولی حرفه‌ای‌تر | | انعطاف‌پذیری | راحت‌تر برای شرط‌های پیچیده | مناسب برای کوئری‌های ساده و مستقیم | | قابل تست بودن | می‌تونی هر مرحله رو جدا تست بزنی | سخت‌تر برای دیباگ مرحله‌ای | | کنترل منطق | شرط‌ها جدا و قابل تغییر | شرط‌ها داخل کوئری، کمتر قابل تغییر در لحظه | | مناسب برای پروژه‌های بزرگ | ✅ بهتر برای منطق پیچیده | مناسب برای لیست‌های سبک و سریع | | تعداد متغیرها | از query چند بار استفاده می‌شه | فقط یک بار تعریف و استفاده می‌شه |
BookSelect.zip
حجم: 17.6M
پروژه مدیریت نویسنده و کتاب
پروژه ASP.Net Core MVC (وب و سی شارپ)
پروژه مدیریت نویسنده و کتاب
الان برات یک لیست کامل و مرتب از اجزای پروژه فعلی آماده می‌کنم تا بتونی در کانالت منتشرش کنی. این لیست هم برای معرفی پروژه‌ات خوبه، هم برای آموزش به دیگران که مثل خودت در مسیر یادگیری هستن. --- ## 📚 پروژه مدیریت نویسنده و کتاب با ASP.NET Core MVC ### ✅ مدل‌ها (Models) -
Author
: شامل
Id
,
FullName
,
Books
-
Book
: شامل
Id
,
Title
,
IsAvailable
,
AuthorId
,
Author
--- ### ✅ روابط بین مدل‌ها - هر نویسنده می‌تواند چند کتاب داشته باشد (
One-to-Many
) - حذف نویسنده فقط در صورتی مجاز است که کتاب نداشته باشد (DeleteBehavior.Restrict) --- ### ✅ کنترلرها (Controllers) -
AuthorController
: لیست، افزودن، ویرایش، حذف نویسنده با شمارش کتاب‌ها -
BookController
: لیست، افزودن، ویرایش، حذف کتاب با فیلتر و صفحه‌بندی -
HomeController
: نمایش نویسنده‌ها و کتاب‌هایشان در صفحه اصلی +
MoreBooks
--- ### ✅ Viewها (صفحات Razor) -
Author/Index
,
Create
,
Edit
,
Delete
با شمارش کتاب‌ها -
Book/Index
,
Create
,
Edit
,
Delete
با فیلتر و صفحه‌بندی -
Home/Index
: نمایش نویسنده‌ها و کتاب‌هایشان (تا ۶ عدد) -
Home/MoreBooks
: نمایش همه کتاب‌های یک نویسنده با صفحه‌بندی --- ### ✅ تنظیمات EF Core در
OnModelCreating
- تعریف رابطه نویسنده و کتاب با DeleteBehavior.Restrict - تنظیم طول فیلدها و الزامی بودن - جلوگیری از حذف نویسنده دارای کتاب - مقدار پیش‌فرض برای
IsAvailable
--- ### ✅ امکانات ویژه - فیلتر کتاب‌ها بر اساس وضعیت و عنوان - صفحه‌بندی برای لیست کتاب‌ها و نویسنده‌ها - پیام هشدار هنگام تلاش برای حذف نویسنده دارای کتاب - طراحی با Bootstrap برای زیبایی و واکنش‌گرایی
پروژه ASP.Net Core MVC (وب و سی شارپ)
پروژه مدیریت نویسنده و کتاب
اگر تمام تنظیماتی که تا الان گفتیم رو در
ModelBuilder
پیاده‌سازی کنی، نتیجه‌اش یک مدل داده‌ای کاملاً حرفه‌ای، امن، و قابل توسعه خواهد بود—درست مثل پروژه‌های واقعی تولیدی. این یعنی: - جلوگیری از خطاهای حذف ناخواسته - اعتبارسنجی داده‌ها از سمت دیتابیس - ساختار تمیز و قابل فهم برای توسعه‌دهنده‌های دیگر - آمادگی برای مهاجرت به پروژه‌های بزرگ‌تر ---
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // جدول نویسنده
    modelBuilder.Entity<Author>(entity =>
    {
        entity.Property(a => a.FullName)
              .IsRequired()
              .HasMaxLength(100);

        entity.HasMany(a => a.Books)
              .WithOne(b => b.Author)
              .HasForeignKey(b => b.AuthorId)
              .OnDelete(DeleteBehavior.Restrict); // جلوگیری از حذف نویسنده دارای کتاب
    });

    // جدول کتاب
    modelBuilder.Entity<Book>(entity =>
    {
        entity.Property(b => b.Title)
              .IsRequired()
              .HasMaxLength(150);

        entity.Property(b => b.IsAvailable)
              .HasDefaultValue(true);

        entity.HasIndex(b => new { b.Title, b.AuthorId })
              .IsUnique(); // جلوگیری از ثبت کتاب تکراری برای یک نویسنده
    });
}
الان کدی که در
OnModelCreating
هست رو به‌صورت لیست کامل و توضیح‌دار برات آماده می‌کنم تا هم برای خودت مرور بشه. این تنظیمات پایه‌ای EF Core هستن که پروژه‌ات رو حرفه‌ای و قابل اعتماد می‌کنن. --- ## 📦 لیست تنظیمات
ModelBuilder
با توضیح کامل ### 1️⃣ entity.Property(a => a.FullName).IsRequired().HasMaxLength(100); - مدل:
Author
- توضیح: فیلد
FullName
باید حتماً مقدار داشته باشه (
IsRequired
) و حداکثر ۱۰۰ کاراکتر باشه. - ✅ جلوگیری از ورود داده‌های ناقص یا طولانی --- ### 2️⃣ entity.HasMany(a => a.Books).WithOne(b => b.Author)... .HasForeignKey(b => b.AuthorId) .OnDelete(DeleteBehavior.Restrict); - مدل: رابطه بین
Author
و
Book
- توضیح: هر نویسنده می‌تونه چند کتاب داشته باشه، ولی اگر کتابی وجود داشته باشه، نویسنده قابل حذف نیست. - ✅ جلوگیری از حذف ناخواسته نویسنده‌ای که کتاب دارد --- ### 3️⃣ entity.Property(b => b.Title).IsRequired().HasMaxLength(150); - مدل:
Book
- توضیح: عنوان کتاب باید وارد شود و حداکثر ۱۵۰ کاراکتر باشد. - ✅ اعتبارسنجی داده‌ها و جلوگیری از خطاهای فرم --- ### 4️⃣ entity.Property(b => b.IsAvailable).HasDefaultValue(true); - مدل:
Book
- توضیح: وضعیت موجود بودن کتاب به‌صورت پیش‌فرض "موجود" تنظیم می‌شود. - ✅ ساده‌سازی فرم افزودن کتاب و کاهش خطای کاربر --- ### 5️⃣ entity.HasIndex(b => new { b.Title, b.AuthorId }).IsUnique(); - مدل:
Book
- توضیح: ترکیب عنوان کتاب و شناسه نویسنده باید یکتا باشد. یعنی یک نویسنده نمی‌تواند دو کتاب با عنوان یکسان داشته باشد. - ✅ جلوگیری از ثبت کتاب‌های تکراری برای یک نویسنده --- ## ✨ نتیجه نهایی | ویژگی | تأثیر در پروژه | |-------|----------------| | اعتبارسنجی فیلدها | جلوگیری از داده‌های ناقص یا اشتباه | | کنترل حذف | حفظ یکپارچگی داده‌ها | | مقدار پیش‌فرض | ساده‌سازی فرم‌ها | | ایندکس یکتا | جلوگیری از تکرار داده‌ها | | رابطه دقیق | ساختار حرفه‌ای و قابل توسعه
BookSelect (2).zip
حجم: 24.7M
🎯 درس جدید: تنظیم دقیق مدل‌ها با ModelBuilder در EF Core در این مرحله از پروژه مدیریت نویسنده و کتاب، وارد دنیای حرفه‌ای Entity Framework Core شدیم. با استفاده از
ModelBuilder
در متد `OnModelCreating`، ساختار دیتابیس رو دقیق‌تر و امن‌تر کردیم. 🔧 تنظیماتی که اضافه شد: 1️⃣ رابطه نویسنده و کتاب هر نویسنده می‌تونه چند کتاب داشته باشه، اما اگر کتابی ثبت شده باشه، حذف نویسنده ممنوعه (DeleteBehavior.Restrict) 2️⃣ اعتبارسنجی فیلدها - نام نویسنده: الزامی و حداکثر ۱۰۰ کاراکتر - عنوان کتاب: الزامی و حداکثر ۱۵۰ کاراکتر 3️⃣ مقدار پیش‌فرض برای وضعیت کتاب کتاب‌ها به‌صورت پیش‌فرض "موجود" ثبت می‌شن (
IsAvailable = true
) 4️⃣ جلوگیری از ثبت کتاب تکراری برای یک نویسنده ترکیب
Title
و
AuthorId
باید یکتا باشه—یعنی یک نویسنده نمی‌تونه دو کتاب با عنوان یکسان داشته باشه 📌 این تنظیمات باعث می‌شن پروژه‌مون هم حرفه‌ای‌تر بشه، هم از خطاهای رایج جلوگیری کنه.