در دنیای برنامهنویسی، یکی از اصول مهمی که تضمین میکند دادههای ما همیشه درست و منسجم باقی بمانند، استفاده از تراکنشها – Transactions است. تصور کنید در حال انتقال پول بین دو حساب بانکی هستید. اگر مبلغ از حساب اول کم شود، اما به حساب دوم نرسد، دادهها ناهماهنگ خواهند شد و این میتواند فاجعهآمیز باشد. در آموزش Transactions در EF Core و Asp.Net Core قصد داریم بهصورت پایه تا پیشرفته تراکنشها را در EF Core بررسی کنیم. همچنین از یک پروژهی عملی با سناریوی انتقال وجه برای درک بهتر مفاهیم استفاده میکنیم و رفتار تراکنشها را در ابزارهایی مثل SQL Server Profiler بررسی خواهیم کرد.
تراکنش – Transaction در Entity Framework Core، ابزاری برای تضمین یکپارچگی دادهها در حین انجام چندین عملیات است. فرض کنید در یک سناریوی بانکی، مبلغی از یک حساب کم شده و باید به حساب دیگری افزوده شود. اگر فقط یکی از این عملیات انجام شود، دادهها ناهماهنگ خواهند بود. Transaction تضمین میکند که تمام عملیات با موفقیت انجام شوند (Commit) یا در صورت بروز خطا، همهی تغییرات به حالت قبل بازگردند (Rollback).
Transaction در EF Core مجموعهای از عملیاتهای مرتبط با پایگاه داده است که باید همه با هم انجام شوند یا هیچکدام. یعنی اگر یک مرحله از عملیات با شکست مواجه شود، کل عملیات لغو – Rollback میشود.
ما قصد داریم سیستمی طراحی کنیم که بتواند بین دو حساب بانکی وجه جابهجا کند. اگر در میانه عملیات مشکلی پیش آمد (مثلاً حساب گیرنده وجود نداشت)، عملیات باید لغو – Rollback شود.
public class BankAccount
{
public int Id { get; set; }
public string Owner { get; set; } = string.Empty;
public decimal Balance { get; set; }
}
public class TransferViewModel
{
[Required]
public int SenderId { get; set; }
[Required]
public int ReciverId { get; set; }
[Range(1000, 1000000, ErrorMessage = "مبلغ باید بین ۱۰۰۰ تا ۱۰۰۰۰۰۰ باشد.")]
public decimal Amount { get; set; }
}
[HttpGet]
public IActionResult Transfer()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult>
Transfer([Bind("SenderId,ReciverId,Amount")]TransferViewModel model)
{
if (!ModelState.IsValid)
return View(model);
using var transaction=await _context.Database.BeginTransactionAsync();
try
{
var Sender = await _context.bankAccounts.FindAsync(model.SenderId);
var Reciver = await _context.bankAccounts.FindAsync(model.ReciverId);
if (Sender == null || Reciver == null)
{
ModelState.AddModelError("", "حساب مبدا یا مقصد یافت نشد.");
return View(model);
}
Sender.Balance -= model.Amount;
Reciver.Balance += model.Amount;
await _context.SaveChangesAsync();
await transaction.CommitAsync();
return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
await transaction.RollbackAsync();
return NotFound(ex.Message);
}
}
using var transaction = await _context.Database.BeginTransactionAsync();
try
{
// تغییرات ۱
// تغییرات ۲
await _context.SaveChangesAsync();
await transaction.CommitAsync();
}
catch
{
await transaction.RollbackAsync();
}
استاد ضمن تشکر لطفا در مورد احراز هویت کاربران هم مطلب بگذارید . متشکرم