2013-03-03 14 views
6

Utilizzo di questo come APIController di base, pensieri? per lo più im curioso di gestione SaveChanges in dispose, contro il metodo ExecuteAsync che ho visto altrove ...Gestione di sessione di base con WebAPI e RavenDB

using System; 
using System.Net.Http; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Web.Http; 
using System.Web.Http.Controllers; 
using Raven.Client; 
using Raven.Client.Document; 

public abstract class RavenDbController : ApiController 
{ 
    private IDocumentStore _documentStore; 

    public IDocumentStore Store 
    { 
     get { return _documentStore ?? (_documentStore = LazyDocStore.Value); } 
     set { _documentStore = value; } 
    } 

    protected override void Initialize(HttpControllerContext controllerContext) 
    { 
     Session = Store.OpenSession(); 
     base.Initialize(controllerContext); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     using (Session) 
     { 
      Session.SaveChanges(); 
     } 
    } 

    public IDocumentSession Session { get; set; } 

} 

risposta

12

Io preferisco usare un attributo filtro di azione al fine di gestire il ciclo di vita dell'oggetto sessione sul controller API di base. Vedere il seguente codice che dimostrano questo approccio:

public class RavenSessionManagementAttribute : ActionFilterAttribute 
{ 
    private readonly IDocumentStore store; 

    public RavenSessionManagementAttribute(IDocumentStore store) 
    { 
     if (store == null) throw new ArgumentNullException("store");  
     this.store = store; 
    } 

    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     var controller = actionContext.ControllerContext.Controller as AbstractApiController; 
     if (controller == null) 
      return; 

     // Can be set explicitly in unit testing 
     if (controller.RavenSession != null) 
      return; 

     controller.RavenSession = store.OpenSession(); 
     controller.RavenSession.Advanced.UseOptimisticConcurrency = true; 
    } 

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
    { 
     var controller = actionExecutedContext.ActionContext.ControllerContext.Controller as AbstractApiController; 
     if (controller == null) 
      return; 

     using (var session = controller.RavenSession) 
     { 
      if (session == null) 
       return; 

      if (actionExecutedContext.Exception != null) 
      { 
       session.SaveChanges(); 
      } 
     } 
    } 
} 

FilterConfig.cs:

public class FilterConfig 
    { 
     public static void RegisterGlobalFilters(HttpFilterCollection filters) 
     { 
      filters.Add(new RavenSessionManagementAttribute(DocumentStoreHolder.Store)); 
     } 
    } 

AbstractApiController.cs:

public abstract class AbstractApiController : ApiController 
    { 
     public IDocumentSession RavenSession { get; set; } 
    } 
+0

sembra grande, io ti do un colpo. –

+0

@FitzchakYitzchaki: Perché dovrei voler utilizzare questo approccio anziché (più semplice) nella domanda? * (Nota: sono un API Web ** e ** principiante RavenDB, quindi è possibile che manchi qualcosa) * –

+1

Perché questo incapsula la funzionalità in un attributo anziché aggiungerlo a un controller di base. Ciò mantiene il controller di base più pulito. –