1

I am not quite familiar about EF but I am using some basic functionality of EF. Recently I got this https://msdn.microsoft.com/en-us/data/dn456843.aspx about transaction in EF6.

I was using SaveChanges() before as I know it will wrap the operation in a transaction. But I notice some of my co-workers are using Database.BeginTransaction(). I search something around and got the following result but I cannot confirm it is correct.

Is that SaveChanges() can still work fine and BeginTransaction is used when SaveChanges cannot fulfill the requirement like wrapping multiple SaveChanges in a single transaction in this post http://www.binaryintellect.net/articles/165bb877-27ee-4efa-9fa3-40cd0cf69e49.aspx?

And in that post, since the db context is the same, I can also add two objects and call SaveChanges() once, which will work fine as well? I guess if we are coping with multiple db context, then we'd better use BeginTransaction to handle multiple SaveChanges() in one transaction?

Edit:

The following is not correct if I would like to have two addition in one transaction? Why?

public void CreateAnimals()  
{  
    context.Set<Cat>.Add(new Dog());  
    context.Set<Cat>.Add(new Cat());   
    context.SaveChanges();  
}

Edit 2:
My main question: When we can use SaveChanges() and when it is a must to use BeginTransaction()? Database.BeginTransaction vs Transactions.TransactionScope does not mention SaveChanges

Community
  • 1
  • 1
woodwind
  • 519
  • 5
  • 10

2 Answers2

3

SaveChanges always executes its DML in a transaction even if you do not specify a transaction explicitly.

Adding entities to the context does not make database calls. The only time DML is executed is when SaveChanges is called. Therefore the code that you posted is atomic (which you call "correct").

Multiple contexts cannot share a transaction (easily). You should not be using multiple contexts anyway in the majority of the cases. Execute your work in one context and one transaction by default.

usr
  • 168,620
  • 35
  • 240
  • 369
  • Thanks usr, the explanation is quite clear. But I still wonder when we should use BeginTransaction instead of SaveChanges since SaveChanges also complete the operations in one transaction – woodwind Apr 08 '15 at 02:14
  • 1
    When you want to execute more than one SaveChanges atomially, or you want to perform reads in the same transaction as other things. – usr Apr 08 '15 at 07:36
0

You shouldn't share contexts. It's not thread safe. If you need reusable code that may or may not be combined into an atomic operation, instantiate individual contexts (they're extremely lightweight) and manage the atomicity at a higher level in the code.

public void Foo()
{
    using ( var context = factory.CreateContext() 
    {
        context.Set<Cat>.Add(new Cat());
        context.SaveChanges();
    }
}

public void Bar()
{
    using ( var context = factory.CreateContext() 
    {
        context.Set<Cat>.Add(new Dog());
        context.SaveChanges();
    }
}

public void CreateAnimals()
{
    using ( var context = factory.CreateContext() )
    {
        var tran = context.Database.BeginTransaction();
        Foo();
        Bar();
        tran.Commit();
    }
}
Jeff Dunlop
  • 893
  • 1
  • 7
  • 20
  • Thanks for the code. But I still wonder why I cannot use the code snippet I just added. I don't think it is related to thread safe. – woodwind Apr 07 '15 at 08:50
  • A transaction on an "outer" context has no effects on "inner" contexts because, in fact, there is no relationship between them. – usr Apr 07 '15 at 16:53