
آموزش Transactions در EF Core
در دنیای برنامهنویسی، یکی از اصول مهمی که تضمین میکند دادههای ما همیشه درست و منسجم باقی بمانند، استفاده از تراکنشها – Transactions است. تصور کنید در حال انتقال پول بین دو حساب بانکی هستید. اگر مبلغ از حساب اول کم شود، اما به حساب دوم نرسد، دادهها ناهماهنگ خواهند شد و این میتواند فاجعهآمیز باشد. در آموزش Transactions در EF Core و Asp.Net Core قصد داریم بهصورت پایه تا پیشرفته تراکنشها را در EF Core بررسی کنیم. همچنین از یک پروژهی عملی با سناریوی انتقال وجه برای درک بهتر مفاهیم استفاده میکنیم و رفتار تراکنشها را در ابزارهایی مثل SQL Server Profiler بررسی خواهیم کرد.
Transaction یا تراکنش چیست ؟
تراکنش – Transaction در Entity Framework Core، ابزاری برای تضمین یکپارچگی دادهها در حین انجام چندین عملیات است. فرض کنید در یک سناریوی بانکی، مبلغی از یک حساب کم شده و باید به حساب دیگری افزوده شود. اگر فقط یکی از این عملیات انجام شود، دادهها ناهماهنگ خواهند بود. Transaction تضمین میکند که تمام عملیات با موفقیت انجام شوند (Commit) یا در صورت بروز خطا، همهی تغییرات به حالت قبل بازگردند (Rollback).
Transaction در EF Core مجموعهای از عملیاتهای مرتبط با پایگاه داده است که باید همه با هم انجام شوند یا هیچکدام. یعنی اگر یک مرحله از عملیات با شکست مواجه شود، کل عملیات لغو – Rollback میشود.
پیاده سازی پروژه Transaction
ما قصد داریم سیستمی طراحی کنیم که بتواند بین دو حساب بانکی وجه جابهجا کند. اگر در میانه عملیات مشکلی پیش آمد (مثلاً حساب گیرنده وجود نداشت)، عملیات باید لغو – Rollback شود.
تعریف Entity Model حساب بانکی
public class BankAccount
{
public int Id { get; set; }
public string Owner { get; set; } = string.Empty;
public decimal Balance { get; set; }
}ساخت ViewModel برای انتقال وجه
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);
}
}کد مربوط به Transaction
متد BeginTransactionAsync : این خط به این معناست که یک تراکنش جدید در سطح دیتابیس شروع شود و EF Core اجازه ندهد عملیات ذخیرهسازی تا زمانی که CommitAsync نشده، بهصورت دائمی در دیتابیس ثبت شوند. وقتی این خط اجرا میشود، عملیاتهایی مثل SaveChangesAsync تا زمانی که transaction.CommitAsync اجرا نشود، بهصورت نهایی در دیتابیس ذخیره نمیشوند. اگر در این بین خطایی رخ دهد و Rollback انجام شود، هیچ تغییری در دیتابیس ثبت نمیشود.
متد RollbackAsync : این دستور تراکنش جاری را به حالت قبل از شروع تراکنش بازمیگرداند. یعنی هر تغییری که از زمان اجرای BeginTransactionAsync تا این لحظه اعمال شده ولی هنوز commit نشده، حذف میشود.
using var transaction = await _context.Database.BeginTransactionAsync();
try
{
// تغییرات ۱
// تغییرات ۲
await _context.SaveChangesAsync();
await transaction.CommitAsync();
}
catch
{
await transaction.RollbackAsync();
}























استاد ضمن تشکر لطفا در مورد احراز هویت کاربران هم مطلب بگذارید . متشکرم
سلام علیرضا جان به نکته خوبی اشاره کردید. دوره EF core در حال پایان است و به زودی به دوره Asp.Net Core برمیگردیم. یکی از فصل ها حتما به احراز هویت کاربران یا همان Identity میپردازیم. مقالات خوبی در این مورد پیدا کردم اطلاعات خودم رو بروز کردم و به صورت مفصل در این خصوص آموزش خواهیم داشت.