/ / Entity Framework y SQL Server Savepoints - .net, .net-4.0, entity-framework-4, sql-server-2008-r2, savepoints

Entity Framework y SQL Server Savepoints: .net, .net-4.0, entity-framework-4, sql-server-2008-r2, savepoints

Le pregunté a pregunta diferente sobre las Transacciones anidadas y la respuesta a mi pregunta me educó lo suficiente como para ayudarme a darme cuenta de que estaba haciendo la pregunta mal. Así que aquí hay una mejor pregunta.

¿Cómo puedo implementar efectivamente los Puntos de Ahorro de SQL Server?enlace 1, enlace 2) con un DAL construido en Entity Framework 4.0?

ME GUSTARÍA escribir el siguiente código y hacer que funcione de manera tal que el servidor SQL Server s SAVEPOINTS

public void Bar()
{
using (var ts = new TransactionScope())
{
var ctx = new Context();
DoSomeStuff(ctx);

bool isSuccessful;

using (var spA = new SavePoint("A")) // <-- this object doesn"t really exist, I don"t think
{
isSuccessful = DoSomeOtherStuff(ctx);
if (isSuccessful)
spA.Complete(); // else rollback bo prior to the beginning of this using block
}

Log(ctx, isSuccessful);

ts.Complete();
}
}

¿Hay alguna forma de hacer algo que se parezca tanto a esto, o algo que funcione bien con EF4? (Utilizamos entidades POCO de seguimiento automático)

Respuestas

0 para la respuesta № 1

Esta no es una respuesta completa, pero sospecho que algo como esto podría estar yendo por el camino correcto. Mi problema es que No estoy completamente seguro de cómo obtener una Transacción Sql mientras estoy en un TransactionScope.

/// <summary>
/// Makes a code block transactional in a way that can be partially rolled-back. This class cannot be inherited.
/// </summary>
/// <remarks>
/// This class makes use of SQL Server"s SAVEPOINT feature, and requires an existing transaction.
/// If using TransactionScope, utilize the DependentTransaction class to obtain the current Transaction that this class requires.
/// </remarks>
public sealed class TransactionSavePoint : IDisposable
{
public bool IsComplete { get; protected set; }
internal SqlTransaction Transaction { get; set; }
internal string SavePointName { get; set; }

private readonly List<ConnectionState> _validConnectionStates = new List<ConnectionState>
{
ConnectionState.Open
};

public TransactionSavePoint(SqlTransaction transaction, string savePointName)
{
IsComplete = false;
Transaction = transaction;
SavePointName = savePointName;

if (!_validConnectionStates.Contains(Transaction.Connection.State))
{
throw new ApplicationException("Invalid connection state: " + Transaction.Connection.State);
}

Transaction.Save(SavePointName);
}

/// <summary>
/// Indicates that all operations within the savepoint are completed successfully.
/// </summary>
public void Complete()
{
IsComplete = true;
}

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
if (!IsComplete)
{
Transaction.Rollback(SavePointName);
}
}
}

Esto sería consumido como tal, muy similar a un TransactionScope:

SqlTransaction myTransaction = Foo();

using (var tsp = new TransactionSavePoint(myTransaction , "SavePointName"))
{
try
{
DoStuff();
tsp.Complete
}
catch (Exception err)
{
LogError(err);
}
}