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
مشاهده در ایتا
دانلود
لیستی کامل و دسته‌بندی‌شده از مهم‌ترین کدهای Fluent API در Entity Framework Core برات آماده کردم—با توضیح فارسی کنار هر کد، تا هم راحت یاد بگیری، هم اشتباه نکنی. --- ## 🔷 ۱. تنظیم پراپرتی‌ها (Property Configuration) entity.Property(x => x.Name).IsRequired(); // اجباری بودن فیلد entity.Property(x => x.Name).HasMaxLength(100); // محدودیت طول entity.Property(x => x.Price).HasColumnType("decimal(18,2)"); // نوع دیتابیس entity.Property(x => x.CreatedAt).HasDefaultValueSql("GETDATE()"); // مقدار پیش‌فرض از SQL entity.Property(x => x.IsActive).HasDefaultValue(true); // مقدار پیش‌فرض بولی entity.Property(x => x.Description).IsUnicode(false); // ذخیره به‌صورت غیر یونیکد --- ## 🔷 ۲. تنظیم کلید اصلی و کلید خارجی entity.HasKey(x => x.Id); // کلید اصلی entity.HasAlternateKey(x => x.Code); // کلید جایگزین (Unique) entity.HasIndex(x => x.Email).IsUnique(); // ایندکس یکتا entity.HasIndex(x => new { x.Title, x.AuthorId }).IsUnique(); // ایندکس ترکیبی یکتا --- ## 🔷 ۳. تنظیم رابطه‌ها (Navigation & Relationships) ### 🔹 یک‌به‌چند (One-to-Many) entity.HasMany(x => x.Books) .WithOne(x => x.Author) .HasForeignKey(x => x.AuthorId) .OnDelete(DeleteBehavior.Restrict); // جلوگیری از حذف نویسنده دارای کتاب ### 🔹 یک‌به‌یک (One-to-One) entity.HasOne(x => x.Profile) .WithOne(x => x.User) .HasForeignKey<UserProfile>(x => x.UserId); ### 🔹 چند‌به‌چند (Many-to-Many) entity.HasMany(x => x.Tags) .WithMany(x => x.Posts) .UsingEntity(j => j.ToTable("PostTags")); // جدول واسط --- ## 🔷 ۴. تغییر نام جدول و ستون entity.ToTable("Authors"); // نام جدول entity.Property(x => x.FullName).HasColumnName("AuthorName"); // نام ستون --- ## 🔷 ۵. تنظیم رفتار حذف (Delete Behavior)
.OnDelete(DeleteBehavior.Cascade); // حذف همراه با وابسته‌ها
.OnDelete(DeleteBehavior.Restrict); // جلوگیری از حذف اگر وابسته وجود دارد
.OnDelete(DeleteBehavior.SetNull); // مقدار کلید خارجی null می‌شود
--- ## 🔷 ۶. تنظیم ترتیب و ترتیب بارگذاری entity.HasIndex(x => x.CreatedAt).HasDatabaseName("IX_CreatedAt"); // نام ایندکس entity.HasData(new Author { Id = 1, FullName = "علیرضا" }); // مقدار اولیه (Seed Data) --- ## ✨ جمله یادسپاری: > «Fluent API یعنی کنترل دقیق ساخت جدول‌ها، رابطه‌ها، محدودیت‌ها و رفتارها—با کدهای زنجیره‌ای و قابل فهم.»
بیایم بررسی کنیم که آیا در این خط ساده:
var author = _context.Authors.Find(id);
استفاده از
.AsNoTracking()
لازم هست یا نه. --- ## 🧩 اول بفهمیم
.Find(id)
چی‌کار می‌کنه -
Find(id)
از EF Core استفاده می‌کنه تا رکوردی با کلید اصلی (
Id
) رو پیدا کنه - این متد همیشه با Tracking کار می‌کنه - یعنی EF تغییرات روی
author
رو ردگیری می‌کنه و اگر بعداً
SaveChanges()
بزنی، تغییرات ذخیره می‌شن --- ## ✅ آیا می‌تونی
.AsNoTracking()
بزنی؟ نه ❌ روی
Find(id)
نمی‌تونی
.AsNoTracking()
بزنی چون
Find()
از ردگیری داخلی EF استفاده می‌کنه و اگر قبلاً اون رکورد رو لود کرده باشه، از حافظه خودش برمی‌داره. --- ## 🔧 اگر بخوای نسخه بدون Tracking داشته باشی: باید از
FirstOrDefault()
یا
SingleOrDefault()
استفاده کنی:
var author = _context.Authors
    .AsNoTracking()
    .FirstOrDefault(a => a.Id == id);
✅ این نسخه داده رو بدون ردگیری میاره، مناسب برای نمایش فقط ❌ ولی اگر بخوای داده رو ویرایش کنی، نباید
AsNoTracking()
بزنی --- ## ✨ جمله یادسپاری: > «
Find(id)
همیشه با Tracking کار می‌کنه—اگر فقط می‌خوای نمایش بدی، از
FirstOrDefault
با
AsNoTracking
استفاده کن.» ---
سلام دوستان عزیز 🌱 می‌خواستم یه نکته مهم رو باهاتون در میون بذارم: من تولیدکننده حرفه‌ای محتوا نیستم، فقط یه علاقه‌مند به برنامه‌نویسی‌ام که مثل خیلی از شما، در مسیر یادگیری قدم گذاشته. با توجه به شرایط کاری‌ام، فقط جمعه‌ها فرصت دارم که تمرین کنم و چیزهایی که یاد می‌گیرم رو با شما به اشتراک بذارم. محتواهایی که منتشر می‌کنم ممکنه پایه‌ای یا برای بعضی‌ها تکراری باشه، اما برای من هر بخش کوچکی از کد یه قدم مهمه برای فهم عمیق‌تر. هدفم اینه که با تمرین‌های مداوم، حتی اگر تعداد پروژه‌ها زیاد بشه، مفاهیم رو به‌خوبی درک کنم و ملکه ذهنم بشه. اگر محتواها ساده یا ابتدایی هستن، منو ببخشید 🙏 من استاد نیستم، فقط یه یادگیرنده‌ام—مثل شما. و هر چیزی که یاد می‌گیرم، با عشق و صداقت منتشر می‌کنم.
BookSelect (4).zip
حجم: 24.7M
صفحه‌بندی پیشرفته با Razor و Bootstrap در این ساختار، فقط چند شماره اطراف صفحه فعلی نمایش داده می‌شن، با دکمه‌های «اول»، «قبلی»، «بعدی» و «آخر» برای حرکت سریع. نقطه‌چین‌ها قبل و بعد از صفحات، به کاربر کمک می‌کنن مسیر طولانی رو بهتر درک کنه. ظاهر با کلاس‌های Bootstrap طراحی شده تا هم زیبا باشه، هم واکنش‌گرا.
Shop & Orders (3).zip
حجم: 24.9M
ساده کردن کدهای enum helper ساده‌سازی نمایش Enum در پروژه‌های MVC برای تبدیل مقادیر Enum به متن قابل‌نمایش (مثل فارسی)، می‌تونیم از ویژگی
[Display(Name = "...")]
استفاده کنیم. به‌جای نوشتن کدهای طولانی در کنترلر، با ساخت یک تابع ساده مثل `GetDisplayName()`، هم در کنترلر و هم در View می‌تونیم متن مناسب رو دریافت کنیم. این کار باعث تمیز شدن کد، کاهش تکرار، و افزایش خوانایی پروژه می‌شه.
پروژه ASP.Net Core MVC (وب و سی شارپ)
ویرایش پروژه
بیایم این چهار بخش کد رو مرحله‌به‌مرحله بررسی کنیم تا دقیقاً بدونی چه تفاوت‌هایی دارن و کد درست برای فرم ویرایش چیه: --- ## ✅ 1. لیست ساده با
Select
و آبجکت ناشناس ViewBag.Authors = _context.Authors .Select(a => new { a.Id, a.FullName }) .ToList(); - فقط یه لیست ساده از
Id
و
FullName
می‌سازه - خروجی:
List<object>
- ❌ برای DropDown قابل استفاده نیست چون ساختارش مناسب
asp-items
نیست --- ## ✅ 2. لیست آماده با
SelectList
ViewBag.Authors = new SelectList(_context.Authors.ToList(), "Id", "FullName"); - ساختار مناسب برای DropDown - خروجی:
SelectList
- ✅ در View با
asp-items="ViewBag.Authors"
قابل استفاده - ❌ اگر مقدار انتخاب‌شده رو مشخص نکنی، DropDown خالی می‌مونه --- ## ✅ 3. بررسی وجود کتاب تکراری در فرم ویرایش
bool exists = _context.Books
    .Any(b => b.Title == book.Title && b.AuthorId == book.AuthorId);

if (exists)
{
    ModelState.AddModelError("Title", "این نویسنده قبلاً کتابی با این عنوان دارد.");
}
- بررسی می‌کنه که آیا همین نویسنده قبلاً کتابی با همین عنوان ثبت کرده یا نه - اگر بله، خطا به
ModelState
اضافه می‌شه و فرم دوباره نمایش داده می‌شه - ✅ این بخش کاملاً درسته و برای جلوگیری از داده‌های تکراری استفاده می‌شه ❌ ولی برای افزودن و برای ویرایش مناسب نیست --- ## ✅ 4. ساخت دستی لیست DropDown با
SelectListItem
ViewBag.Authors = _context.Authors .Select(a => new SelectListItem { Value = a.Id.ToString(), Text = a.FullName }) .ToList(); - خروجی:
List<SelectListItem>
- ✅ قابل استفاده در View با
asp-items="ViewBag.Authors"
- می‌تونی برای هر آیتم
Selected = true
بزنی - مناسب برای فرم‌هایی که مقدار انتخاب‌شده رو از قبل داری --- ## 🔍 نتیجه‌گیری کلی: | روش | خروجی | مناسب DropDown | کنترل انتخاب‌شده | |------|--------|----------------|-------------------| | Select با آبجکت ناشناس | List<object> | ❌ | ❌ | | SelectList | SelectList | ✅ | با پارامتر چهارم | | SelectListItem دستی | List<SelectListItem> | ✅ | با
Selected = true
| --- ## ✨ جمله یادسپاری: > «در فرم ویرایش، یا از SelectList با پارامتر چهارم استفاده کن، یا از SelectListItem با شرط Selected—هر دو روش حرفه‌ای هستن.»
[Required(ErrorMessage = "قیمت محصول الزامی است")] [Range(1, 1000000, ErrorMessage = "قیمت باید بین ۱ تا ۱,۰۰۰,۰۰۰ باشد.")] [Column(TypeName = "decimal(18,2)")] [Display(Name = ":قیمت")] public decimal Price { get; set; } بیایم هر کد رو جداگانه بررسی کنیم تا تفاوتشون کاملاً برات روشن بشه: --- 🧮 1. [Column(TypeName = "decimal(18,2)")] این خط مربوط به تنظیم نوع ستون در دیتابیس هست: - decimal(18,2) یعنی: - مجموعاً ۱۸ رقم - ۲ رقم بعد از اعشار - یعنی می‌تونی عددی مثل 1234567890123456.78 ذخیره کنی 📌 این فقط روی ساختار دیتابیس تأثیر داره، نه روی اعتبارسنجی فرم یا محدودیت‌های ورود کاربر. --- ✅ 2. [Range(1, 1000000, ErrorMessage = "...")] این خط مربوط به اعتبارسنجی در فرم و سمت سرور هست: - یعنی کاربر فقط می‌تونه عددی بین ۱ تا ۱,۰۰۰,۰۰۰ وارد کنه - اگر عددی خارج از این بازه وارد بشه، پیام خطا نمایش داده می‌شه 📌 این فقط روی ورودی کاربر تأثیر داره، نه روی نوع ستون در دیتابیس. --- 🧠 نتیجه‌گیری | ویژگی | مربوط به | توضیح | |-------|-----------|--------| | decimal(18,2) | دیتابیس | ظرفیت ذخیره عدد بزرگ با دقت بالا | | Range(1,1000000) | اعتبارسنجی | محدودیت ورود عدد توسط کاربر | 🔹 پس حتی اگر دیتابیس اجازه بده عددی مثل 9999999999999999.99 ذخیره بشه، اعتبارسنجی فرم جلوی ورود عدد بالاتر از 1,000,000 رو می‌گیره.
پروژه ASP.Net Core MVC (وب و سی شارپ)
[Required(ErrorMessage = "قیمت محصول الزامی است")] [Range(1, 1000000, ErrorMessage = "قیمت باید بین
اگر منظورت اینه که در این خط:
csharp
[Column(TypeName = "decimal(18,2)")]
عدد ۱۸ رو به ۸ تغییر بدیم و بشه:
csharp
[Column(TypeName = "decimal(8,2)")]
بله، می‌تونی این کار رو انجام بدی، ولی باید بدونی دقیقاً چه تأثیری داره: --- 🔍 تفاوت decimal(18,2) با decimal(8,2) | نوع | توضیح | |-----|-------| | decimal(18,2) | عددی با حداکثر ۱۸ رقم، که ۲ رقم آن بعد از اعشار است. یعنی تا 9999999999999999.99 قابل ذخیره است. | | decimal(8,2) | عددی با حداکثر ۸ رقم، که ۲ رقم آن بعد از اعشار است. یعنی تا 999999.99 قابل ذخیره است. | 🔹 پس اگر از decimal(8,2) استفاده کنی، بیشترین مقدار قابل ذخیره می‌شه حدود ۹۹۹ هزار تومان 🔹 اگر محصولاتی با قیمت بالاتر داری، ممکنه خطای overflow یا ذخیره ناقص رخ بده --- ✅ پیشنهاد من چون در اعتبارسنجی Range(1, 1000000) استفاده کردی، decimal(8,2) کفایت می‌کنه و با اون بازه هماهنگه. پس بله، می‌تونی با خیال راحت عدد ۱۸ رو به ۸ تغییر بدی تا فضای دیتابیس بهینه‌تر بشه.
مشکل اینجاست که وقتی عدد خیلی بزرگ وارد می‌کنی، قبل از اینکه اعتبارسنجی
[Range]
فرصت بررسی داشته باشه، مدل‌سازی (`Model Binding`) در ASP.NET Core با خطای `OverflowException` متوقف می‌شه**—چون عدد از محدوده‌ی `int` یا `decimal` خارج شده و تبدیل مستقیم شکست می‌خوره. --- ## ✅ راه‌حل قطعی: اعتبارسنجی قبل از تبدیل برای اینکه اعتبارسنجی واقعاً کار کنه و خطای سرریز رخ نده، باید: --- ### 1. **نوع فیلد ورودی را از `int` به `string` تغییر بده در مدل ویو (ViewModel) یا مدل فرم، فیلد عددی را به
string
تبدیل کن تا اول اعتبارسنجی انجام بشه، بعد تبدیل:
[Required]
[RegularExpression(@"^\d{1,7}$", ErrorMessage = "عدد باید بین ۱ تا ۹۹۹۹۹۹۹ باشد.")]
public string QuantityInput { get; set; }
🔹 این یعنی فقط عددهای تا ۷ رقم مجاز هستن 🔹 هیچ تبدیل به
int
انجام نمی‌شه تا زمانی که خودت کنترل کنی --- ### 2. در کنترلر، تبدیل امن انجام بده
if (!ModelState.IsValid)
{
    return View(model); // ✅ نمایش پیام خطا
}

if (!int.TryParse(model.QuantityInput, out int quantity))
{
    ModelState.AddModelError("QuantityInput", "عدد وارد شده معتبر نیست.");
    return View(model);
}

if (quantity < 1 || quantity > 1000000)
{
    ModelState.AddModelError("QuantityInput", "عدد باید بین ۱ تا ۱,۰۰۰,۰۰۰ باشد.");
    return View(model);
}

// ✅ حالا می‌تونی با quantity ادامه بدی
--- ### 3. در View از `Html.ValidationMessageFor` استفاده کن
<div class="form-group">
    <label for="QuantityInput">تعداد</label>
    <input asp-for="QuantityInput" class="form-control" />
    <span asp-validation-for="QuantityInput" class="text-danger"></span>
</div>
--- ## 🎯 نتیجه نهایی - عدد خیلی بزرگ باعث خطای سرریز نمی‌شه چون اول به‌صورت
string
گرفته می‌شه - اعتبارسنجی کامل انجام می‌شه - پیام خطا به‌صورت زیبا نمایش داده می‌شه - هیچ خطای
Unhandled Exception
یا
OverflowException
نمی‌بینی
SmartReports.zip
حجم: 25.3M
پروژه داشبورد گزارش‌گیری و نمودارها
پروژه ASP.Net Core MVC (وب و سی شارپ)
پروژه داشبورد گزارش‌گیری و نمودارها
> پروژه : SmartReports - داشبورد گزارش‌گیری و نمودارها --- ## ✅ لیست کامل پروژه سوم و کارهایی که انجام دادیم ### 1. هدف پروژه ساخت یک داشبورد گزارش‌گیری با تمرکز بر: - سفارش‌ها، مشتریان، محصولات - نمایش نمودارهای آماری با Chart.js - طراحی واکنش‌گرا با Bootstrap - اجرای آفلاین با فایل‌های محلی JS و CSS --- ### 2. ساختار پروژه | بخش | توضیحات | |-----|---------| |
Controllers/ReportsController.cs
| کنترلر اصلی گزارش‌ها شامل اکشن‌های روزانه، مشتریان، محصولات | |
Models/Report/*.cs
| مدل‌های گزارش مثل
DailyOrderReport
,
TopProductReport
,
CustomerActivityReport
| |
Views/Reports/*.cshtml
| ویوهای گزارش‌ها و نمودارها | |
wwwroot/js/
| فایل‌های آفلاین: chart.js,
jquery v3.6.0.js
,
bootstrap v4.6.2.js
| |
wwwroot/css/
| فایل آفلاین: bootstrap-v4.6.2.css | | Layout.cshtml | اضافه کردن فایل‌های آفلاین و ساخت ظاهر حرفه‌ای | | appsettings.json | اتصال به دیتابیس و تنظیمات پروژه | --- ### 3. اکشن‌هایی که نوشتیم #### 🔹
DailyOrders()
- گروه‌بندی سفارش‌ها بر اساس تاریخ - محاسبه تعداد سفارش و مجموع قیمت - استفاده از
Include(o => o.Products)
- اضافه کردن
AsNoTracking()
برای بهینه‌سازی - ارسال داده‌ها به View برای نمایش نمودار #### 🔹
TopProducts()
- نمایش محصولات پرفروش بر اساس تعداد سفارش - ساخت مدل
TopProductReport
- مرتب‌سازی نزولی بر اساس فروش #### 🔹
CustomerActivity()
و
ActiveCustomers()
- نمایش همه مشتریان و مشتریان فعال - محاسبه تعداد سفارش و آخرین تاریخ سفارش - ارسال عنوان پویا با ViewBag.Title --- ### 4. نمودارها با Chart.js - ساخت نمودار ستونی برای سفارش‌ها - رنگ‌بندی سفارشی ستون‌ها - نمایش تعداد سفارش بالای هر ستون با
DataLabels
- حذف مجموع از Tooltip و نمایش فقط مقدار هر ستون - عنوان پویا مثل:
نمودار تعداد سفارش‌ها — مجموع: ۱۰ عدد
--- ### 5. رفع خطاها و بهینه‌سازی‌ها - اضافه کردن
AsNoTracking()
برای جلوگیری از ردیابی اضافی - اصلاح
decimal(8,2)
به
decimal(18,2)
برای جلوگیری از خطای Overflow - بررسی خطای
OverflowException
و تبدیل امن عددهای بزرگ - استفاده از
string
یا
double?
برای ورودی عددی با کنترل دستی - طراحی فوتر با Bootstrap که روی دکمه‌ها نیفته - تنظیم فایل‌های آفلاین برای اجرای بدون اینترنت --- ### 6. فایل‌های آفلاین که استفاده کردی
<!-- CSS -->
<link href="~/css/bootstrap-v4.6.2.css" rel="stylesheet" />

<!-- JS -->
<script src="~/js/jquery v3.6.0.js"></script>
<script src="~/js/bootstrap v4.6.2.js"></script>
<script src="~/js/chart.js"></script>
--- ## 🎯 نتیجه نهایی پروژه سوم - داشبورد گزارش‌گیری کامل و قابل توسعه - نمودارهای حرفه‌ای و قابل شخصی‌سازی - اجرای آفلاین بدون نیاز به CDN - رعایت اصول معماری MVC و بهینه‌سازی EF Core - پایه‌ای برای آموزش تولید محتوا و پروژه‌های واقعی