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 :)
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?
Related
I want to find a way to control EF's underlying db connection & transaction to make sure my application is using only one connection at a time during one transaction (I will need to support both Oracle and SQL Server).
I found this good article which comes with a lot of recommendations, but brings up (like all the other articles I have read) the TransactionScope. Well, I would like to stay away of TransactionScope, if possible...
Could I have a solution for this playing with only pure DbConnection & DbTransaction or this is simply impossible or wrong?
Even more, I found this article here, stating at section :
"Specifying Your Own Transaction"
Just as you can override the default behavior with connections, you
can also control transaction functionality. If you explicitly create
your own transaction, SaveChanges will not create a DbTransaction. You
won't create a System.Common.DbTransaction, though. Instead, when
creating your own transactions, you need to use a
System.Transaction.TransactionScope object.
But there is no explaination...
I am using Entity Framework 5.0. Could you please help me understand in order to choose correct for my application? It would be ideal to show me some good patterns of usage.
Thanks in advance!
Note: I am planning this because of the transactions escalating to DTC for Oracle Data Provider.
Entity Framework 6 has two features which may help with this:
Explicit Transaction Support
Ability to create a DbContext from a DbConnection.
If you did want to use EF5, you'd need to use a TransactionScope:
var context = new MyContext();
using (var transaction = new TransactionScope())
{
MyItem item = new MyItem();
context.Items.Add(item);
context.SaveChanges();
item.Name = "Edited name";
context.SaveChanges();
transaction.Complete();
}
As mentioned in the linked article, you will need to reference System.Transactions to get TransactionScope.
Entity Framework maintains its own transaction which is sufficient. However it gives you flexibility of committing or discarding the changes in transaction. If you do not call SaveChanges() method then it will discard the transaction. Also if you are using the same DbContext for many transactions, then it would be using same connection. If you use two or more DbContext at the same time, then it will use separate connections which is ideal situation. Here is a very important point I would like to make is that it would be a waste of Entity Framework technology to implement own transaction. If you want to do so, then I would suggest to use your own DB implementation in traditional way.
I am using NServiceBus with Distributed Transactions. Normally this works fantastic. Either my message succeeds or fails. All or nothing.
However, I am also trying to record diagnostic data to my database. This is done on a separate ObjectContext. For that, I would like it to save to the database regardless of the success or failure of the Distributed Transaction.
Is there a way to have one (and only one) data context connect to the database outside the distributed transaction? (And keep the rest of them in?)
Try this to suppress your ambient distributed transaction for auditing:
using (new TransactionScope(TransactionScopeOption.Suppress))
{
// Create logging context and audit your data
}
One option (if using3.0) is to create a UoW:
http://andreasohlund.net/2011/11/21/unit-of-work-in-nservicebus-3-0/
And in there suppress the transaction and do the logging.
NSB has a built in way to do auditing. I would recommend turning this on and dealing with the logging/audit trail in another endpoint.
I have a piece of code i recently expanded but now must use a transaction. It looks like it can only be access while in a transaction but looks like doesnt make me feel comfortable. Using SQLite and ADO.NET i wrote if(cmd.Transaction==null) but it is null and in a transaction. How should i check?
NOTE: I will be using this code with TSQL in the future. This is a quick prototype with SQLite
-edit- i was thinking of nesting transactions but this code generates a piece of sql and uses a command to add parameters too. So adding a nested transaction would take a lot of modification.
Depending on the nature of the SQL and its fit in the application, it may be more appropriate for you to nest transactions, ensuring a transaction is present regardless of the context of the call.
For example, you could wrap the calling code in a TransactionScope block. If there is a transaction present, this will have no real effect on the operation. If there is no transaction present, it will create a transaction and ensure the ADO.NET code participates in the transaction.
This approach only works if you're happy for the SQL to be executed as a single operation. If it should only be called as part of a larger transaction, this approach doesn't help.
To know for sure that a transaction is present, you have to check for the explicit transaction on the ADO.NET command (as you have above) and also the presence of an ambient transaction from the System.Transactions programming model using the Transaction.Current property.
I'm creating and dropping databases on the fly for some integration tests. I'm doing all the database management at the ADO.NET level. For the tests I'm using Entity Framework because the entities is one part of what I am testing. The problem is that after I do this:
using (ProjectEntities db = new ProjectEntities(cs)) {
}
I cannot drop the database anymore. It says it is in use. How do I release it so it can be dropped?
I actually had the same problem at the ADO.NET level and what I did was:
new SqlCommand("USE [master]", DatabaseConnection).ExecuteNonQuery();
but I'm not sure how to perform something with the same effect for the Entity Framework connection. I've trying manually disposing the db object (although the using clause should guarantee that) and I've also tried manually closing the db.Connection. Neither helped. If I could run SQL directly no the Entity Framework connection, I believe I'll be able to do it. Or maybe there's another way?
You might need to explicitly close all connections, I believe that the connection are being pooled and it's one of the pooled connections that is still maintaining an active connection to the DB. Try using SqlConnection.ClearAllPools
I blogged about a similar issue in Entity Framework Object Context - AWAITING COMMAND.
I'm using Visual Studio 2008, C#, SQLite via System.Data.SQLite with SubSonic 3. My application has gotten to a state where I need to upgrade the database schema (add columns, triggers, etc) then add new records via SubSonic generated ActiveRecord objects - all within the scope of a single transaction so that any failures could be nicely rolled back.
Ideally, this is sort of what I was hoping to do:
Begin Transaction
try
Update Schema to latest version
Use SubSonic objects to add new records/modify existing
Commit Transaction
catch
Rollback Transaction
Unfortunately, this doesn't work. All the schema changes are currently being via SubSonic.Query.CodingHorror, which doesn't seem to respect transactions. Is there a way to perform both schema changes and SubSonic data changes within the scope of a single transaction?
I think I found the answer to my question: use the same database connection for all actions and use transaction on that one database connection. Since I hadn't told SubSonic how to handle all the database connections for me - it used the default method, one connection per lookup or created object or CodingHorror. Since transactions can't span database connections, the behavior I saw was fully expected.
Once I created my own database connection and did the lookups, creates and CodingHorror schema changes on it, all transaction stuff begin to work properly.