문제

웹 애플리케이션 내에서 AutoFac을 사용하여 Nhibernate 트랜잭션을 관리하는 가장 좋은 방법은 무엇입니까?

세션에 대한 나의 접근 방식입니다

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

을 위한 ITransaction, 나는 가지고있다 예를 찾았습니다 Google 코드에서는하지만 의존합니다 HttpContext.Current.Error 롤백 여부를 결정할 때.

더 나은 솔루션이 있습니까? 그리고 어떤 범위가 트랜잭션 ~해야 한다 가지다?

도움이 되었습니까?

해결책

나는 얼마 전에 이것을 게시했다 :

http://groups.google.com/group/autofac/browse_thread/f10badba5fe0d546/e64f2e757df94e61?lnk=gst&q=transaction#e64f2e757df94e61

인터셉터에 로깅 기능이 있고 [트랜잭션] 속성도 클래스에서도 사용할 수 있도록 수정되었습니다.

[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;
    }
}

다른 팁

AutoFac을 사용하면 동일한 컨테이너 스코프 메소드를 사용하지만 동일한 세션을 저장소/DAO 객체에 전달하는 대신 컨테이너 스코프인 인 Unitofwork를 전달합니다. 작업 단위는 이것을 생성자에 있습니다.

    private readonly ISession _session;
    private ITransaction _transaction;

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

그리고 처분은 다음과 같습니다.

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

    }

나는 (AB) 이것을 관리하기 위해 AutoFAC에서 결정 론적 처분 물건을 사용하고 있으며, 나는 그것을 좋아합니다.

또 다른 것은 기본적으로 ASPNET 환경을 목표로하고 거래가 웹 요청과 관련이 있다는 의식적인 결정을 내렸다는 것입니다. 따라서 웹 요청 패턴 당 트랜잭션.

이 때문에 ihttpmodule 에서이 오류 처리 코드를 수행 할 수 있습니다.

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

나는 nhibernate를 보지 않았다.

나는 보통 거래를 직접 관리합니다 ..

public ActionResult Edit(Question q){
try {
 using (var t = repo.BeginTransaction()){
  repo.Save(q);
  t.Commit();
  return View();
 }
 catch (Exception e){
  ...
 }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top