پروژه 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باید یکتا باشه—یعنی یک نویسنده نمیتونه دو کتاب با عنوان یکسان داشته باشه 📌 این تنظیمات باعث میشن پروژهمون هم حرفهایتر بشه، هم از خطاهای رایج جلوگیری کنه.
زمان:
حجم:
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 استفاده کنی