2013-03-03 12 views
6

Używanie tego jako podstawowego APIControllera, myśli? przeważnie jestem ciekaw obsługi SaveChanges w zbyć, w porównaniu z metodą ExecuteAsync które widziałem gdzie indziej ...Podstawowa obsługa sesji z WebAPI i 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; } 

} 

Odpowiedz

12

Wolę za pomocą atrybutu filtra działania w celu zarządzania cyklem życia obiektu sesji na podstawowy kontroler API. Zobacz poniższy kod, który wykazania tego podejścia:

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

wygląda świetnie, będę dać mu szansę. –

+0

@FitzchakYitzchaki: Dlaczego miałbym używać tego zamiast (łatwiejszego) podejścia w pytaniu? * (Uwaga: jestem Web API ** i ** RavenDB dla początkujących, więc możliwe, że czegoś brakuje) * –

+1

Ponieważ to enkapsuluje funkcjonalność w atrybucie, zamiast dodawać ją do kontrolera bazowego. Dzięki temu sterownik podstawowy jest bardziej czysty. –