Как работает сущностный фреймворк SaveChanges? - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь понять, как EF создает запросы БД из манипуляций с объектами в коде. Мой тестовый сценарий прост:

using(var context = new Context())
{
var entity = context.Entities.First();
entity.A = "TST";
entity.B = "WrongValue";
context.SaveChanges();
}

Моя идея - проверить, как EF справляется с транзакцией. Измените A с правильным значением и измените B с неправильным значением (несуществующий FK) Я отслеживаю, что происходит в БД SQL Server. Я выполняю код и ничего не меняю в БД, что и ожидалось. Странная часть в том, что есть два независимых запроса SQL, и я не понимаю, как EF возвращает первый.

1 Ответ

0 голосов
/ 01 мая 2018

Код Entity Framework и EntityFramework core имеют открытый исходный код. Вы можете проверить код на

  1. Entity Framework - Ссылка
  2. Ядро Entity Framework - Ссылка

Если вы видите внутренний код Метод сохранения (вставил снимок кода ниже), то вы можете проверить, что он внутренне создает транзакцию, если внешняя транзакция не указана.

    internal int SaveChangesInternal(SaveOptions options, bool executeInExistingTransaction)
    {
        AsyncMonitor.EnsureNotEntered();

        PrepareToSaveChanges(options);

        var entriesAffected = 0;

        // if there are no changes to save, perform fast exit to avoid interacting with or starting of new transactions
        if (ObjectStateManager.HasChanges())
        {
            if (executeInExistingTransaction)
            {
                entriesAffected = SaveChangesToStore(options, null, startLocalTransaction: false);
            }
            else
            {
                var executionStrategy = DbProviderServices.GetExecutionStrategy(Connection, MetadataWorkspace);
                entriesAffected = executionStrategy.Execute(
                    () => SaveChangesToStore(options, executionStrategy, startLocalTransaction: true));
            }
        }

        ObjectStateManager.AssertAllForeignKeyIndexEntriesAreValid();
        return entriesAffected;
    }

Таким образом, приведенный ниже код будет внутренне обернут внутри транзакции, которую вы можете проверить в SQL Profiler.

using(var context = new Context())
{
var entity = context.Entities.First();
entity.A = "TST";
entity.B = "WrongValue";
context.SaveChanges();
}

Однако профилировщик SQL не запускает запись транзакций, поэтому вам необходимо настроить это в параметрах трассировки. Посмотрите на скриншот ниже для новой настройки трассировки в SQL profiler, здесь я проверил Show All events. После этого отображается категория Transaction. Вы можете подписаться на события Begin Tran, Commit Tran и Rollback Tran для проверки выписок по транзакциям. Когда вы запустите свой сценарий, вы увидите, что Begin и Rollback должны быть зарегистрированы. enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...