Issue: (With Sql 2005)
I have been able to solve very similar problem using this code fragment:
var connection = new EntityConnection("name=MyEntities");
connection.Open();
var tran = connection.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);
try
{
var dataContext = new MyEntities(connection);
//CRUD operation1
//CRUD operation2
//CRUD operation3 ...
Assert.AreEqual(expected, actual);
}
catch
{
throw;
}
finally
{
tran.Rollback();
connection.Close();
}
Where MyEntities
is the EF DataModel.
The crucial part is the setting of the transaction: System.Data.IsolationLevel.ReadUncommitted
.
Using this isolation level SQL queries can read you changes done inside the transaction.
Also you need to explicitly create a connection as I do on the first and second line.
I couldn't make it work using TransactionScope
unfortunately.
From MSDN;
"SaveChanges operates within a transaction. SaveChanges will roll back that transaction and throw an exception if any of the dirty ObjectStateEntry objects cannot be persisted. "
So it seems that there is no need to to explicitly add your own transaction handling through TransactionScope
.
In my case I delete all records from a Table through plain SQL since EF doesn't provide a functionality for this. After that I add some new entities - but when it fails, the table shouldn't be empty. The use of MSDTC (TransactionScope) seems not possible for me. I reduced the transaction to the DB:
My code:
using (var transaction = context.Connection.BeginTransaction())
{
// delete all
base.DeleteAll<TESTEntity>(context);
// add all
foreach (var item in items)
{
context.TESTEntity.AddObject(item);
}
try
{
context.SaveChanges();
transaction.Commit();
return true;
}
catch (Exception ex)
{
Logger.Write("Error in Save: " + ex, "Error");
transaction.Rollback();
return false;
}
}
And here the helper functions
protected void DeleteAll<TEntity>(ObjectContext context) where TEntity : class
{
string tableName = GetTableName<TEntity>(context);
int rc = context.ExecuteStoreCommand(string.Format(CultureInfo.InvariantCulture, "DELETE FROM {0}", tableName));
}
protected string GetTableName<TEntity>(ObjectContext context) where TEntity : class
{
string snippet = "FROM [dbo].[";
string sql = context.CreateObjectSet<TEntity>().ToTraceString();
string sqlFirstPart = sql.Substring(sql.IndexOf(snippet) + snippet.Length);
string tableName = sqlFirstPart.Substring(0, sqlFirstPart.IndexOf("]"));
return tableName;
}