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 (وب و سی شارپ)
ویرایش پروژه
بیایم این چهار بخش کد رو مرحله‌به‌مرحله بررسی کنیم تا دقیقاً بدونی چه تفاوت‌هایی دارن و کد درست برای فرم ویرایش چیه: --- ## ✅ 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 - پایه‌ای برای آموزش تولید محتوا و پروژه‌های واقعی
ترجمه_مقادیر_فنی_به_متن_فارسی_در_سی_شارپ__کالبدشکافی_الگوی_Enum.mp3
زمان: حجم: 5.4M
ترجمه مقادیر فنی به متن فارسی در سی شارپ کالبد شکافی الگوی enum در ASP.Net Core MVC ساخته شده از هوش مصنوعی
پروژه ASP.Net Core MVC (وب و سی شارپ)
ترجمه مقادیر فنی به متن فارسی در سی شارپ کالبد شکافی الگوی enum در ASP.Net Core MVC ساخته شده از هو
بیایم این کد رو کلمه به کلمه و خط به خط بررسی کنیم تا دقیقاً بفهمی چطور enum با DisplayAttribute و EnumHelper ترکیب شده و در کنترلر استفاده شده. --- ✅ بخش اول: تعریف Enum با نام‌های نمایشی
csharp
public enum OrderStatus
{
    [Display(Name = "در انتظار")]
    Pending,

    [Display(Name = "تأیید شده")]
    Confirmed,

    [Display(Name = "ارسال شده")]
    Shipped,

    [Display(Name = "تحویل داده شده")]
    Delivered,

    [Display(Name = "لغو شده")]
    Canceled
}
🔹 enum OrderStatus تعریف یک نوع شمارشی برای وضعیت سفارش‌ها 🔹 [Display(Name = "...")] مشخص کردن نام نمایشی فارسی برای هر مقدار مثلاً OrderStatus.Pending در View به صورت «در انتظار» نمایش داده می‌شه --- ✅ بخش دوم: کلاس کمکی برای گرفتن نام نمایشی
csharp
public static class EnumHelper
{
    public static string GetDisplayName(Enum value)
    {
        var field = value.GetType().GetField(value.ToString());
        var attr = field?.GetCustomAttribute<DisplayAttribute>();
        return attr?.Name ?? value.ToString();
    }
}
🔹 GetDisplayName(Enum value) متدی برای گرفتن نام نمایشی از Enum 🔹 value.GetType().GetField(value.ToString()) دریافت اطلاعات فیلد مربوط به مقدار Enum 🔹 GetCustomAttribute<DisplayAttribute>() بررسی اینکه آیا ویژگی [Display(Name = "...")] وجود دارد یا نه 🔹 attr?.Name ?? value.ToString() اگر DisplayAttribute وجود داشت، مقدار Name را برمی‌گرداند اگر نبود، نام اصلی Enum را برمی‌گرداند (مثلاً Pending) --- ✅ بخش سوم: اکشن Index برای صفحه اصلی فروشگاه
csharp
public IActionResult Index()
{
    var recentOrders = _context.Orders
        .Include(o => o.OrderProducts)
            .ThenInclude(op => op.Product)
        .OrderByDescending(o => o.OrderDate)
        .Take(5)
        .ToList()
        .Select(o => new
        {
            o.Id,
            o.CustomerName,
            o.OrderDate,
            StatusText = EnumHelper.GetDisplayName(Enum.Parse<OrderStatus>(o.Status)),
            ProductCount = o.OrderProducts.Count,
            TotalAmount = o.OrderProducts.Sum(op => op.Product.Price * op.Quantity)
        })
        .ToList();

    var topProducts = _context.Products
        .Where(p => p.IsAvailable)
        .OrderByDescending(p => p.Price)
        .Take(5)
        .ToList();

    ViewBag.RecentOrders = recentOrders;
    ViewBag.TopProducts = topProducts;

    return View();
}
🔹 Include و ThenInclude برای بارگذاری سفارش‌ها و محصولات مرتبط 🔹 OrderByDescending(o => o.OrderDate) مرتب‌سازی سفارش‌ها از جدید به قدیم 🔹 Enum.Parse<OrderStatus>(o.Status) تبدیل رشته‌ی Status به مقدار enum از نوع OrderStatus 🔹 EnumHelper.GetDisplayName(...) گرفتن نام فارسی وضعیت سفارش 🔹 ProductCount و TotalAmount تعداد محصولات و مجموع قیمت سفارش --- ✅ بخش چهارم: اکشن OrderDetails
csharp
public IActionResult OrderDetails(int id)
{
    var order = _context.Orders
        .Include(o => o.OrderProducts)
            .ThenInclude(op => op.Product)
        .FirstOrDefault(o => o.Id == id);

    if (order == null)
        return NotFound();

    var status = OrderStatus.Shipped;
    var displayName = EnumHelper.GetDisplayName(status);
    ViewBag.StatusText = displayName;

    return View(order);
}
🔹 Include و ThenInclude بارگذاری سفارش و محصولات مرتبط 🔹 OrderStatus.Shipped مقدار Enum به‌صورت مستقیم 🔹 EnumHelper.GetDisplayName(status) گرفتن نام فارسی «ارسال شده» --- ✅ بخش پنجم: اکشن ProductDetails
csharp
public IActionResult ProductDetails(int id)
{
    var product = _context.Products.Find(id);

    if (product == null)
        return NotFound();

    return View(product);
}
🔹 Find(id) یافتن محصول با شناسه 🔹 return View(product) ارسال محصول به View برای نمایش جزئیات --- 🎯 نتیجه‌گیری - Enum با DisplayAttribute برای نمایش فارسی وضعیت‌ها استفاده شده - کلاس EnumHelper به‌صورت عمومی قابل استفاده در همه جا هست - در کنترلر، مقدار Enum از دیتابیس تبدیل می‌شه و نام نمایشی گرفته می‌شه - این ساختار هم خوانا، هم قابل توسعه، و هم مناسب برای چندزبانه‌سازیه
بیایم این سه اکشن مهم رو با مثال‌های ساده و توضیح مرحله‌به‌مرحله بررسی کنیم تا دقیقاً بفهمی چه اتفاقی می‌افته و چطور با هم کار می‌کنن. این سه اکشن مربوط به سناریویی هستن که: > کاربر می‌خواد محصولی رو ویرایش کنه، ولی اگر اون محصول در سفارش‌ها استفاده شده باشه و بخواد غیرفعالش کنه، باید اول تأیید کنه که از سفارش‌ها حذف بشه. --- ✅ ۱. اکشن [HttpPost] Edit — ویرایش محصول
csharp
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(int id, Product updatedProduct)
🔹 هدف: ویرایش اطلاعات محصولی که شناسه‌اش id هست با داده‌های جدیدی که از فرم اومده (updatedProduct) --- 🔹 مرحله‌به‌مرحله: 1. پیدا کردن محصول اصلی از دیتابیس
csharp
   var product = _context.Products.Find(id);
   if (product == null)
       return NotFound();
   
2. بررسی تکراری بودن نام محصول
csharp
   bool exists = _context.Products
       .Any(p => p.Name == updatedProduct.Name && p.Id != id);
   if (exists)
       ModelState.AddModelError("Name", "نام محصول تکراری است.");
   
3. بررسی اینکه آیا کاربر می‌خواد محصول فعال رو غیرفعال کنه
csharp
   if (product.IsAvailable && !updatedProduct.IsAvailable)
   {
       var hasOrders = _context.OrderProducts
           .Any(op => op.ProductId == product.Id);
       if (hasOrders)
       {
           TempData["ConfirmDeleteFromOrders"] = true;
           TempData["ProductId"] = product.Id;
           return RedirectToAction("ConfirmProductRemoval");
       }
   }
   
4. اگر همه چیز درست بود، ذخیره تغییرات
csharp
   if (ModelState.IsValid)
   {
       product.Name = updatedProduct.Name;
       product.Price = updatedProduct.Price;
       product.IsAvailable = updatedProduct.IsAvailable;

       _context.SaveChanges();
       TempData["Success"] = "محصول با موفقیت ویرایش شد.";
       return RedirectToAction(nameof(Index));
   }
   
5. اگر خطا وجود داشت، نمایش فرم با خطاها
csharp
   return View(updatedProduct);
   
--- ✅ ۲. اکشن ConfirmProductRemoval — نمایش تأیید حذف از سفارش‌ها
csharp
public IActionResult ConfirmProductRemoval()
🔹 هدف: نمایش صفحه‌ای به کاربر که تأیید کنه آیا می‌خواد محصولی که در سفارش‌ها استفاده شده، حذف بشه یا نه --- 🔹 مرحله‌به‌مرحله: 1. گرفتن شناسه محصول از TempData
csharp
   int productId = (int)TempData["ProductId"];
   
2. پیدا کردن محصول از دیتابیس
csharp
   var product = _context.Products.Find(productId);
   
3. ارسال محصول به View برای نمایش اطلاعات و دکمه تأیید
csharp
   return View(product);
   
--- ✅ ۳. اکشن [HttpPost] RemoveProductFromOrders — حذف محصول از سفارش‌ها
csharp
[HttpPost]
public IActionResult RemoveProductFromOrders(int productId)
🔹 هدف: حذف همه سفارش‌هایی که شامل این محصول هستن، و سپس غیرفعال کردن محصول --- 🔹 مرحله‌به‌مرحله: 1. پیدا کردن همه سفارش‌های مربوط به محصول
csharp
   var orderItems = _context.OrderProducts
       .Where(op => op.ProductId == productId)
       .ToList();
   
2. حذف همه سفارش‌ها از جدول OrderProducts
csharp
   _context.OrderProducts.RemoveRange(orderItems);
   
3. پیدا کردن محصول و غیرفعال کردنش
csharp
   var product = _context.Products.Find(productId);
   product.IsAvailable = false;
   
4. ذخیره تغییرات در دیتابیس
csharp
   _context.SaveChanges();
   
5. نمایش پیام موفقیت و برگشت به صفحه اصلی
csharp
   TempData["Success"] = "محصول از سفارش‌ها حذف شد و غیرفعال گردید";
   return RedirectToAction("Index");
   
--- 🎯 جمع‌بندی تصویری
ویرایش محصول
   ↓
اگر غیرفعال شد و در سفارش‌ها بود
   ↓
نمایش تأییدیه حذف از سفارش‌ها
   ↓
اگر کاربر تأیید کرد
   ↓
حذف سفارش‌ها + غیرفعال کردن محصول
---
بررسی تکراری بودن نام محصول csharp bool exists = _context.Products .Any(p => p.Name == updatedProduct.Name && p.Id != id); if (exists) ModelState.AddModelError("Name", "نام محصول تکراری است."); بذار با مثال ساده و دقیق برات توضیح بدم تا کاملاً جا بیفته: --- ✅ سناریو: بررسی تکراری بودن نام محصول در اکشن ویرایش فرض کن در دیتابیس محصولی داریم با:
plaintext
Id = 1
Name = "گوشی"
حالا کاربر می‌خواد محصولی با Id = 1 رو ویرایش کنه. --- 🔹 حالت اول: کاربر نام محصول رو به "گوشی" تغییر می‌ده ولی محصول دیگری با همین نام وجود دارد
csharp
bool exists = _context.Products
    .Any(p => p.Name == updatedProduct.Name && p.Id != id);
این شرط یعنی: > آیا محصولی با همین نام وجود دارد ولی شناسه‌اش با محصول فعلی فرق دارد؟ ✅ اگر محصول دیگری با نام "گوشی" و Id ≠ 1 وجود داشته باشه، شرط exists == true می‌شه و خطا نمایش داده می‌شه: «نام محصول تکراری است.» --- 🔹 حالت دوم: کاربر فقط قیمت یا وضعیت محصول را تغییر می‌دهد و نام را همان "گوشی" باقی می‌گذارد در این حالت: - updatedProduct.Name == product.Name - و چون Id == id، شرط p.Id != id باعث می‌شه خود محصول فعلی در بررسی تکراری بودن محاسبه نشه ✅ بنابراین شرط exists == false می‌شه ✅ و خطای "نام محصول تکراری است" نمایش داده نمی‌شه --- 🎯 نتیجه‌گیری | وضعیت | آیا خطا نمایش داده می‌شود؟ | |-------|-----------------------------| | تغییر نام به نام محصول دیگری | ✅ بله، چون نام تکراری است و شناسه فرق دارد | | نام محصول تغییر نکرده | ❌ نه، چون خودش است و تکراری محسوب نمی‌شود |
Shop & Orders (4).zip
حجم: 24.9M
حذف @functions و آوردن تابع کمکی در کنترلر order