مقدمه

تاکنون، تمرکز ما بر روی خواندن داده‌ها از پایگاه داده با استفاده از کوئری‌های LINQ بوده است. اما یک بخش حیاتی از هر برنامه‌ی داده‌محور، قابلیت تغییر داده‌ها است. این شامل افزودن رکوردهای جدید، به‌روزرسانی رکوردهای موجود و حذف رکوردهای قدیمی می‌شود. Entity Framework Core این عملیات را با استفاده از مکانیزم ردیابی تغییرات (Change Tracking) که در درس قبل با آن آشنا شدیم، فوق‌العاده ساده می‌کند.

فرآیند کلی برای هر نوع ویرایش داده شامل سه مرحله است:

  1. ایجاد یک نمونه از هاDbContext.
  2. انجام عملیات مورد نظر بر روی DbSetها (افزودن، به‌روزرسانی یا حذف اشیاء).
  3. فراخوانی متد SaveChanges() برای ارسال تمام تغییرات به پایگاه داده در قالب یک تراکنش واحد.

در این درس، هر یک از این عملیات را به صورت عملی بررسی خواهیم کرد.

افزودن داده‌های جدید

برای افزودن یک رکورد جدید به پایگاه داده، کافی است یک نمونه‌ی جدید از کلاس موجودیت خود بسازید، آن را به DbSet مربوطه اضافه کرده و سپس SaveChanges() را فراخوانی کنید.

Copy Icon Program.cs
using (var db = new MyDbContext())
{
    // 1. Create a new object.
    var newProduct = new Product { Name = "Monitor", Price = 250m, Stock = 15 };

    // 2. Add it to the DbSet. EF Core starts tracking it in an 'Added' state.
    db.Products.Add(newProduct);

    // 3. Save the changes. EF Core generates and executes an INSERT statement.
    int affectedRows = db.SaveChanges();

    Console.WriteLine($"{affectedRows} row(s) added.");
    Console.WriteLine($"New product ID is: {newProduct.Id}");
}

پس از فراخوانی SaveChanges، EF Core یک دستور INSERT را برای پایگاه داده تولید و اجرا می‌کند. یک ویژگی بسیار مفید این است که پس از اجرای دستور، EF Core به طور خودکار مقدار کلید اصلی (Id) که توسط پایگاه داده تولید شده را در شیء newProduct ما قرار می‌دهد.

به‌روزرسانی داده‌های موجود

به لطف مکانیزم ردیابی تغییرات، به‌روزرسانی داده‌ها بسیار ساده است. شما فقط باید موجودیت مورد نظر را از پایگاه داده بخوانید، پراپرتی‌های آن را تغییر دهید و SaveChanges را فراخوانی کنید.

Copy Icon Program.cs
using (var db = new MyDbContext())
{
    // 1. Find the entity to update. This entity is now being tracked.
    var productToUpdate = db.Products.FirstOrDefault(p => p.Name == "Mouse");

    if (productToUpdate != null)
    {
        // 2. Modify its properties.
        productToUpdate.Price += 5m;

        // 3. Save the changes. EF Core detects the modification and sends an UPDATE statement.
        db.SaveChanges();
        Console.WriteLine("Product price updated.");
    }
}

هنگامی که SaveChanges فراخوانی می‌شود، ردیاب تغییرات متوجه می‌شود که پراپرتی Price در شیء productToUpdate تغییر کرده است. در نتیجه، یک دستور UPDATE بهینه تولید می‌کند که تنها ستون Price را برای آن رکورد خاص به‌روزرسانی می‌کند.

حذف داده‌ها

فرآیند حذف نیز کاملاً مشابه به‌روزرسانی است. ابتدا موجودیت مورد نظر را پیدا کرده، آن را با استفاده از متد Remove برای حذف علامت‌گذاری می‌کنیم و سپس SaveChanges را فراخوانی می‌نماییم.

Copy Icon Program.cs
using (var db = new MyDbContext())
{
    // 1. Find the entity to delete.
    var productToDelete = db.Products.Find(1); // Find by primary key.

    if (productToDelete != null)
    {
        // 2. Mark the entity for deletion.
        db.Products.Remove(productToDelete);

        // 3. Save the changes. EF Core generates and executes a DELETE statement.
        db.SaveChanges();
        Console.WriteLine("Product deleted.");
    }
}

در این مثال، از متد Find استفاده کرده‌ایم که یک راه بهینه برای پیدا کردن یک موجودیت بر اساس کلید اصلی آن است. اگر موجودیت با آن کلید از قبل در حافظه‌ی DbContext ردیابی شده باشد، Find بدون ارسال کوئری به پایگاه داده آن را برمی‌گرداند.

SaveChanges و تراکنش‌ها

یک نکته‌ی بسیار مهم در مورد SaveChanges این است که این متد تمام تغییرات (افزودن، به‌روزرسانی و حذف) را در قالب یک تراکنش (Transaction) واحد به پایگاه داده ارسال می‌کند. این یعنی یا تمام عملیات با موفقیت انجام می‌شوند، یا اگر حتی یکی از آن‌ها با شکست مواجه شود، تمام عملیات لغو (rollback) شده و پایگاه داده به وضعیت اولیه‌ی خود بازمی‌گردد. این ویژگی، یکپارچگی و سلامت داده‌های شما را تضمین می‌کند.