Frage

Was ist der beste Ansatz NHibernate Transaktion innerhalb von Web-Anwendung mit Autofac zu verwalten?

Mein Ansatz zur Sitzung

builder.Register(c => c.Resolve<ISessionFactory>().OpenSession())
       .ContainerScoped();

Für ITransaction, ich habe ein Beispiel auf Google Code, aber es stützt sich auf HttpContext.Current.Error bei der Entscheidung, ob ein Rollback.

Gibt es eine bessere Lösung? Und was Umfang NHibernate Transaktion sollte haben?

War es hilfreich?

Lösung

ich gepostet vor einer Weile:

http: // Gruppen .google.com / Gruppe / Autofac / browse_thread / thread / f10badba5fe0d546 / e64f2e757df94e61? lnk = gst & q = Transaktion # e64f2e757df94e61

Modifizierte, so dass die Abfangjäger hat Logging-Funktionen und [Transaktion] Attribut kann auch auf einer Klasse verwendet werden.

[global::System.AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class TransactionAttribute : Attribute
{
}


public class ServicesInterceptor : Castle.Core.Interceptor.IInterceptor
{
    private readonly ISession db;
    private ITransaction transaction = null;

    public ServicesInterceptor(ISession db)
    {
        this.db = db;
    }

    public void Intercept(IInvocation invocation)
    {
        ILog log = LogManager.GetLogger(string.Format("{0}.{1}", invocation.Method.DeclaringType.FullName, invocation.Method.Name));

        bool isTransactional = IsTransactional(invocation.Method);
        bool iAmTheFirst = false;

        if (transaction == null && isTransactional)
        {
            transaction = db.BeginTransaction();
            iAmTheFirst = true;
        }

        try
        {
            invocation.Proceed();

            if (iAmTheFirst)
            {
                iAmTheFirst = false;

                transaction.Commit();
                transaction = null;
            }
        }
        catch (Exception ex)
        {
            if (iAmTheFirst)
            {
                iAmTheFirst = false;

                transaction.Rollback();
                db.Clear();
                transaction = null;
            }

            log.Error(ex);
            throw ex;
        }
    }

    private bool IsTransactional(MethodInfo mi)
    {
        var atrClass = mi.DeclaringType.GetCustomAttributes(false);

        foreach (var a in atrClass)
            if (a is TransactionAttribute)
                return true;

        var atrMethod = mi.GetCustomAttributes(false);

        foreach (var a in atrMethod)
            if (a is TransactionAttribute)
                return true;

        return false;
    }
}

Andere Tipps

Wenn ich Autofac verwenden benutze ich den gleichen Behälter scoped Methode, sondern die gleiche Sitzung meine Repository / DAO Objekte geben ich einen UnitOfWork passieren, dass Container scoped ist. Die Einheit der Arbeit hat dies im Konstruktor.

    private readonly ISession _session;
    private ITransaction _transaction;

    public UnitOfWork(ISession session)
    {
        _session = session;
        _transaction = session.BeginTransaction();
    }

Und die dispose ist:

    public void Dispose()
    {
        try
        {
            if (_transaction != null &&
                            !_transaction.WasCommitted &&
                            !_transaction.WasRolledBack)
                _transaction.Commit();
            _transaction = null;
        }
        catch (Exception)
        {
            Rollback();
            throw;
        }

    }

Ich bin (ab) die deterministische Entsorgung Sachen in Autofac, um mit diesem zu verwalten, und auch ich irgendwie wie es.

Die andere Sache ist, dass ich im Grunde nur eine ASPNet Umgebung Targeting und machte eine bewusste Entscheidung, die eine Transaktion auf eine Web-Anfrage gebunden ist. So eine Transaktion pro Web-Anfrage Muster.

Aus diesem Grund kann ich diesen Fehler machen Code Handhabung in einem IHttpModule:

    void context_Error(object sender, System.EventArgs e)
    {
        _containerProvider.RequestContainer.Resolve<IUnitOfWork>().Rollback();
    }

Ich habe nicht einen Blick auf NHibernate.Burrow zu eng genommen, aber ich bin sicher, dass es etwas gibt es, dass die meisten dies tut.

ich die Transaktion selbst in der Regel verwalten ..

public ActionResult Edit(Question q){
try {
 using (var t = repo.BeginTransaction()){
  repo.Save(q);
  t.Commit();
  return View();
 }
 catch (Exception e){
  ...
 }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top