Как выполнить транзакцию с контекстом объекта Entity Framework? - PullRequest
3 голосов
/ 07 марта 2011

Я создал очень простую базу данных, используя Entity Framework 4. Я хотел бы иметь возможность использовать транзакции для сущностей, но я не могу предотвратить откат изменений.Мне действительно просто нужен способ отказаться от временных изменений в сущностях, прежде чем они будут сохранены в базе данных.

Например, в следующем коде используется контекст объекта инфраструктуры объектов "MusicContainer".Внутри TransactionScope создается объект Artist.Затем транзакция заканчивается без завершения;поэтому я ожидаю, что транзакция будет отменена.Но программа запускается так, как будто я никогда не создавал TransactionScope;после завершения TransactionScope строка music.SaveChanges () сохраняет объект в базе данных.

class Program
{
    static void Main(string[] args)
    {
        using (MusicContainer music = new MusicContainer())
        {
            using (TransactionScope transaction = new TransactionScope())
            {
                Artist artist = new Artist { Name = "Test" };
                music.Artists.AddObject(artist);
            }
            // The transaction ended without Complete(); shouldn't the changes be abandoned?
            music.SaveChanges();
        }
    }
}

Если структура сущностей не использует TransactionScope так, как я ожидаю, здесь, как я могу получить требуемую функциональность?У меня есть несколько обстоятельств, когда вызывающий функции проходит в MusicContainer, и мне нужно оставить MusicContainer в чистом состоянии, прежде чем я вернусь из функции (т. Е. Отката изменений, чтобы они не были случайно сохранены с другим SaveChanges, называемымна том же объекте MusicContainer).

Ответы [ 3 ]

7 голосов
/ 07 марта 2011

В этом сценарии TransactionScope вам вообще не нужен, SaveChanges() - это все, что нужно - если у вас есть другой блок using с MusicContainer, это будет в отдельной транзакции и не будетсохранить любые изменения в вашем текущем блоке using.TransactionScope требуется только для транзакций, охватывающих несколько контекстов БД.

В общем случае контекст следует использовать только для единицы работы, состоящей из связанных операций, после того как они завершены, вызовите SaveChanges().Откройте новый контекст для каждой отдельной, не связанной единицы работы.Сказав это, просто используйте это в вашем сценарии:

        using (MusicContainer music = new MusicContainer())
        {
                Artist artist = new Artist { Name = "Test" };
                music.Artists.AddObject(artist);
                music.SaveChanges();
        }
2 голосов
/ 07 марта 2011

Ваши SaveChanges находятся не в том месте.

class Program
{
    static void Main(string[] args)
    {
        using (MusicContainer music = new MusicContainer())
        {
            using (TransactionScope transaction = new TransactionScope())
            {
                Artist artist = new Artist { Name = "Test" };
                music.Artists.AddObject(artist);
                music.SaveChanges();
            }
            // The transaction ended without Complete(); the changes are abandoned?
        }
    }
}

Вы не должны повторно использовать MusicContainer, если транзакция не удалась. Создайте новый для каждой Единицы работы

0 голосов
/ 07 марта 2011

Платформа сущностей должна иметь возможность использовать TransactionScope .Вам нужно запустить новый TransactionScope, если вам нужно откатить изменения, примененные только этим методом.

 using (MusicContainer music = new MusicContainer())
   {
     using (TransactionScope transaction = new TransactionScope(TransactionScopeOptions.RequiresNew))
          {
              Artist artist = new Artist { Name = "Test" };
              music.Artists.AddObject(artist);
              music.SaveChanges();
              scope.Complete(); 
          }
    }
...