В любой реляционной базе данных поддержание целостности базы данных очень важно, и Транзакция является одним из способов поддержания целостности базы данных. Если у вас есть ситуация, когда вам нужно вставить данные в несколько таблиц, и если вставка данных в одну из таблиц завершается неудачно, вы должны всегда откатывать другие транзакции вставки. Тот же сценарий существует для операций обновления или удаления. Если транзакции отсутствуют, вы получите много ненужных данных в таблицах. Entity Framework является одним из самых популярных ORM в .NET World. Итак, в этом посте мы узнаем, как мы можем использовать транзакции с Entity Framework 6.
Транзакция и Entity Framework 6
Entity Framework внутренне поддерживает транзакцию при вызове метода SaveChanges (). Таким образом, все операции вставки и обновления при одном вызове метода сохранения изменений будут выполняться в одной транзакции. Но если вы хотите обернуть несколько методов SaveChanges () в одну транзакцию, в более ранних версиях Entity Framework нет встроенных функций.
Теперь, с Entity Framework 6.0, у нас есть два встроенных API для транзакций:
DbContext.Database.BeginTransaction
Этот вызов API позволит нам начать транзакцию для нескольких изменений сохранения. Вы можете объединить столько операций, сколько вы хотите в одной транзакции, и, следовательно, либо все они будут выполнены успешно, то транзакция будет зафиксирована. Если произойдет какое-либо исключение, транзакция будет отменена.
DbContext.Database.UseTransaction
Иногда нам нужно использовать транзакцию, которая запускается вне рамок сущности. В этом случае этот вызов API позволяет нам также использовать эту транзакцию с Entity Framework.
В этом сообщении мы будем использовать Begin Transaction. В будущем я планирую написать отдельный пост в блоге о том, как использовать существующую транзакцию с платформой сущностей.
Итак, достаточно теории, давайте создадим консольное приложение, чтобы лучше его понять.

В этом приложении мы собираемся использовать два модельных класса, называемые категорией и продуктом. Мы сохраним их обе в одной транзакции и попытаемся понять, как транзакция работает с Entity Framework.
Модель категории указана ниже:
namespace EFWithTransactions
{
    public class Category
    {
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }
    }
}Вот модель продукта:
using System.ComponentModel.DataAnnotations.Schema;
namespace EFWithTransactions
{
    public class Product
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        [ForeignKey("Category")]
        public int CategoryId { get; set; }
        public virtual Category Category { get; set; }
    }
}Здесь вы можете видеть, что у меня есть идентификатор категории в продукте, к которому относится продукт. Я создал свой класс dbcontext, как показано ниже:
using System.Data.Entity;
namespace EFWithTransactions
{
    public class ProductDbContext : DbContext
    {
        public ProductDbContext()
            : base("ProductConnectionString")
        {
        }
        public DbSet<Category> Categories { get; set; }
        public DbSet<Product> Products { get; set; }
    }
}Метод Main консольного приложения показан ниже, который иллюстрирует реальный сценарий, когда исключение может произойти во время нескольких изменений сохранения ().
using System;
namespace EFWithTransactions
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ProductDbContext productDbContext = new ProductDbContext())
            {
                using (var transaction = productDbContext.Database.BeginTransaction())
                {
                    try
                    {
                        //saving category
                        Category category = new Category
                        {
                            CategoryName = "Clothes"
                        };
                        productDbContext.Categories.Add(category);
                        productDbContext.SaveChanges();
                        // Throw some error to check transaction
                        // Comment this to make transactions sucessfull
                        // throw new Exception("Custom Exception");
                        //saving product
                        Product product = new Product
                        {
                            ProductName = "Blue Denim Shirt",
                            CategoryId = category.CategoryId
                        };
                        productDbContext.Products.Add(product);
                        productDbContext.SaveChanges();
                        Console.Write("Cateogry and Product both saved");
                        transaction.Commit();
                    }
                    catch (Exception exception)
                    {
                        transaction.Rollback();
                        Console.WriteLine("Transaction Roll backed due to some exception");
                    }
                }
            }
            Console.ReadKey();
        }
    }
}Если вы внимательно изучите приведенный выше код, вы увидите, что у меня есть два метода сохранения изменений: один для категории и другой для продукта. Я также использовал метод BeginTransaction для запуска новой транзакции.
Я добавил одно пользовательское исключение, чтобы проиллюстрировать, что что-то не так с этой транзакцией. Также существует блок try / catch для обработки любых исключений и откат транзакции. Если все пойдет хорошо, он совершит транзакцию.
Теперь давайте запустим это приложение, и следующий результат — ожидаемый результат, так как мы сгенерировали исключение.
В результате данные не были вставлены в базу данных.
Теперь давайте прокомментируем новую часть, которая вызывает исключение.
//throw new Exception("Custom Exception");Когда мы снова запустим наше приложение, ожидаемый результат будет возвращен.
Теперь у нас есть данные в базе данных.
В результате у нас есть действительно хороший способ использовать Transaction в Entity Framework. Надеюсь, вам понравится.
Оставайтесь с нами, чтобы узнать больше!




