3

I am writing unit test cases for testing a framework. The unit test adds and modifies the data in an existing database. I need to rollback all the changes done to database after a test finishes, i.e. delete the rows added and revert the rows modified.

I am using Entity Framework 6 for accessing the database. The underlying database is SQL Server. Is there any support provided by EF6 to achieve this?

Presently I am storing the changes in a list and I refer the this list for cleaning up the database. But using this approach leaves some residue randomly. I am not sure of the reason though, maybe some race condition or something.

Looking for some minimal and smart alternative for it. Thanks in advance :)

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Madhur Maurya
  • 1,016
  • 4
  • 19
  • 42

1 Answers1

4

you can wrap your test in a transaction and don't commit changes:

using (TransactionScope scope = new TransactionScope()) {
    //do your stuff
}

But for unit testing propouses you can use Effort - Entity Framework Unit Testing Tool which provide in-memory database operations.

EDITED to reply last comments

You can use an overloaded TransactionScope contructor to control the IsolationLevel, so you can choose to read uncommited changes or not.

If your proxy isn't inside the Transaction, please, check that the connection string is the same, so ado.net can identify the connection and enlist the connection in the same transaction. If the connection string is not the same, you probably will need to activate the Distributed Transaction Coordinator. Here you have an explanation how DTC scalation occurs: TransactionScope automatically escalating to MSDTC on some machines?

Community
  • 1
  • 1
mnieto
  • 3,744
  • 4
  • 21
  • 37
  • Thanks a lot for the answer. I am still new in this technology. Can I use more than one DB Contexts inside the `TransactionScope` sequentially and without writing `context.saveChanges()` at the end of each DB context scope ? I hope I made my point clear. – Madhur Maurya Feb 20 '16 at 20:15
  • 2
    @MadhurMaurya yes you can. The only thing you may get cought up on is if the connection string is different between the DB Contexts or you have multiple open contexts you need to make sure the "[Distributed Transaction Coordinator Service](http://i.stack.imgur.com/pfxxS.png)" is enabled on the machine that does the unit tests or else make sure that you only use one open connection per `TransactionScope`. – Scott Chamberlain Feb 20 '16 at 20:58
  • @ScottChamberlain What if I need to use multiple open connection per transaction scope. – Madhur Maurya Apr 21 '16 at 07:47
  • 1
    @MadhurMaurya `TransactionScope` can handle multiple connections at once, you just need to make sure the "Distributed Transaction Coordinator" windows service is running then just use your multiple connections all within the `using` block. – Scott Chamberlain Apr 21 '16 at 13:27
  • @ScottChamberlain I am having hard time dealing with transaction scope :( The tests makes a proxy call to service which again modifies database. I believe the transactions done by proxy service are not covered in transaction scope. Also the service call needs to access some data ( or even alter ) that is added inside the transaction scope. How can it alter the data that is not actually written to database ( i. e still a part of uncommited transaction) . – Madhur Maurya Apr 21 '16 at 14:53
  • 1
    @MadhurMaurya: I've edited my response to cover your last comments. – mnieto Apr 25 '16 at 13:58
  • If I have two `context.SaveChanges()` calls (on the same context) inside a `TransactionScope` and the second one fails, will that revert the first one? – Wes Thompson Dec 01 '16 at 20:18