servicestack,funq,Ravendb,servicestack,Funq" /> servicestack,funq,Ravendb,servicestack,Funq" />

将RavenDB与ServiceStack一起使用

将RavenDB与ServiceStack一起使用,ravendb,servicestack,funq,Ravendb,servicestack,Funq,我读了Phillip Haydon关于如何将NHibernate/RavenDB与ServiceStack一起使用的帖子。 我看不出每次我需要从db获得这样的东西时,获取IDocumentStore并打开新会话有什么意义: public class FooService : ServiceBase<Foo> { public IDocumentStore RavenStore{ get; set; } protected override object Run(Pr

我读了Phillip Haydon关于如何将NHibernate/RavenDB与ServiceStack一起使用的帖子。
我看不出每次我需要从db获得这样的东西时,获取IDocumentStore并打开新会话有什么意义:

public class FooService : ServiceBase<Foo>
{
    public IDocumentStore RavenStore{ get; set; }

    protected override object Run(ProductFind request)
    {
        using (var session = RavenStore.OpenSession())
        {
            // Do Something...

            return new FooResponse{/*Object init*/};
        }
    }
}
public class FooService : ServiceBase<Foo>
{
    public IRavenSession RavenSession { get; set; }

    protected override object Run(ProductFind request)
    {
        // Do Something with RavenSession...

        return new FooResponse {/*Object init*/};
    }
}
公共类FooService:ServiceBase
{
公共IDocumentStore RavenStore{get;set;}
受保护的覆盖对象运行(ProductFind请求)
{
使用(var session=RavenStore.OpenSession())
{
//做点什么。。。
返回新的FooResponse{/*对象init*/};
}
}
}
为什么我不能对每个请求使用一个会话,当请求结束时,根据响应状态提交更改或回滚更改

如果我的方法很好,那么我如何实施它? 以下是我的尝试:

我创建了这个类:

    public class RavenSession : IRavenSession
    {
        #region Data Members

        private readonly IDocumentStore _store;
        private IDocumentSession _innerSession;

        #endregion

        #region Properties

        public IDocumentSession InnerSession
        {
            get { return _innerSession ?? (_innerSession = _store.OpenSession()); }
        }

        #endregion

        #region Ctor

        public RavenSession(IDocumentStore store)
        {
            _store = store;
        }

        #endregion

        #region Public Methods

        public void Commit()
        {
            if (_innerSession != null)
            {
                try
                {
                    InnerSession.SaveChanges();
                }
                finally
                {
                    InnerSession.Dispose();
                }
            }
        }

        public void Rollback()
        {
            if (_innerSession != null)
            {
                InnerSession.Dispose();
            }
        }

        #endregion

        #region IDocumentSession Delegation

        public ISyncAdvancedSessionOperation Advanced
        {
            get { return InnerSession.Advanced; }
        }

        public void Delete<T>(T entity)
        {
            InnerSession.Delete(entity);
        }

        public ILoaderWithInclude<object> Include(string path)
        {
            return InnerSession.Include(path);
        }

        public ILoaderWithInclude<T> Include<T, TInclude>(Expression<Func<T, object>> path)
        {
            return InnerSession.Include<T, TInclude>(path);
        }

        public ILoaderWithInclude<T> Include<T>(Expression<Func<T, object>> path)
        {
            return InnerSession.Include(path);
        }

        public T Load<T>(string id)
        {
            return InnerSession.Load<T>(id);
        }

        public T[] Load<T>(params string[] ids)
        {
            return InnerSession.Load<T>(ids);
        }

        public T Load<T>(ValueType id)
        {
            return InnerSession.Load<T>(id);
        }

        public T[] Load<T>(IEnumerable<string> ids)
        {
            return InnerSession.Load<T>(ids);
        }

        public IRavenQueryable<T> Query<T, TIndexCreator>() where TIndexCreator : AbstractIndexCreationTask, new()
        {
            return InnerSession.Query<T, TIndexCreator>();
        }

        public IRavenQueryable<T> Query<T>()
        {
            return InnerSession.Query<T>();
        }

        public IRavenQueryable<T> Query<T>(string indexName)
        {
            return InnerSession.Query<T>(indexName);
        }

        public void Store(dynamic entity, string id)
        {
            InnerSession.Store(entity, id);
        }

        public void Store(object entity, Guid etag, string id)
        {
            InnerSession.Store(entity, etag, id);
        }

        public void Store(object entity, Guid etag)
        {
            InnerSession.Store(entity, etag);
        }

        public void Store(dynamic entity)
        {
            InnerSession.Store(entity);
        }

        #endregion

    }
public class RavenSession:IRavenSession
{
#区域数据成员
私有只读IDocumentStore\u存储;
私有IDocumentSession\u innerSession;
#端区
#区域属性
公共IDocumentSession InnerSession
{
获取{return\u innerSession??(\u innerSession=\u store.OpenSession());}
}
#端区
#区域导体
公共RavenSession(IDocumentStore)
{
_商店=商店;
}
#端区
#区域公共方法
公共无效提交()
{
如果(_innerSession!=null)
{
尝试
{
InnerSession.SaveChanges();
}
最后
{
Dispose();
}
}
}
公共无效回滚()
{
如果(_innerSession!=null)
{
Dispose();
}
}
#端区
#区域文件会议代表团
公共iSyncAdvanced会话操作高级
{
获取{return InnerSession.Advanced;}
}
公共作废删除(T实体)
{
删除(实体);
}
公共ILoaderWithInclude(字符串路径)
{
返回InnerSession.Include(路径);
}
公共ILoaderWithInclude(表达式路径)
{
返回InnerSession.Include(路径);
}
公共ILoaderWithInclude(表达式路径)
{
返回InnerSession.Include(路径);
}
公共T加载(字符串id)
{
返回InnerSession.Load(id);
}
公共T[]加载(参数字符串[]ID)
{
返回InnerSession.Load(id);
}
公共T负载(ValueType id)
{
返回InnerSession.Load(id);
}
公共T[]加载(IEnumerable ID)
{
返回InnerSession.Load(id);
}
public IRavenQueryable Query(),其中TIndexCreator:AbstractIndexCreationTask,new()
{
返回InnerSession.Query();
}
公共可愤怒查询()
{
返回InnerSession.Query();
}
公共IRavenQueryable查询(字符串indexName)
{
返回InnerSession.Query(indexName);
}
公共无效存储(动态实体,字符串id)
{
存储(实体,id);
}
公共无效存储(对象实体、Guid etag、字符串id)
{
存储(实体、etag、id);
}
公共无效存储(对象实体,Guid etag)
{
存储(实体,etag);
}
公共void存储(动态实体)
{
存储(实体);
}
#端区
}
现在我的服务是这样的:

public class FooService : ServiceBase<Foo>
{
    public IDocumentStore RavenStore{ get; set; }

    protected override object Run(ProductFind request)
    {
        using (var session = RavenStore.OpenSession())
        {
            // Do Something...

            return new FooResponse{/*Object init*/};
        }
    }
}
public class FooService : ServiceBase<Foo>
{
    public IRavenSession RavenSession { get; set; }

    protected override object Run(ProductFind request)
    {
        // Do Something with RavenSession...

        return new FooResponse {/*Object init*/};
    }
}
公共类FooService:ServiceBase
{
公共会话RavenSession{get;set;}
受保护的覆盖对象运行(ProductFind请求)
{
//用瑞文塞斯做点什么。。。
返回新的FooResponse{/*对象init*/};
}
}
但是我仍然需要找到一种方法来知道提交/回滚更改的请求何时结束。
我发现最好的方法是使用ResponseFilter:

public class AppHost : AppHostBase
{
    public AppHost()
        : base("", typeof (Foo).Assembly, typeof (FooService).Assembly)
    {
    }

    public override void Configure(Container container)
    {
        // Some Configuration...

        this.ResponseFilters.Add((httpReq, httpResp, respnseDto) =>
                                     {
                                         var currentSession = (RavenSession) this.Container.Resolve<IRavenSession>();

                                         if (!httpResp.IsErrorResponse())
                                         {
                                             currentSession.Commit();
                                         }
                                         else
                                         {
                                             currentSession.Rollback();
                                         }
                                     });

        // Some Configuration...
    }
}
公共类AppHost:AppHostBase
{
公共AppHost()
:base(“),typeof(Foo.Assembly,typeof(FooService.Assembly)
{
}
公共覆盖无效配置(容器)
{
//一些配置。。。
this.ResponseFilters.Add((httpReq、httpResp、responsedto)=>
{
var currentSession=(RavenSession)this.Container.Resolve();
如果(!httpResp.IsErrorResponse())
{
currentSession.Commit();
}
其他的
{
currentSession.Rollback();
}
});
//一些配置。。。
}
}
我确信有更好的方法可以做到这一点,但如何过滤ServiceStack中的响应 在中反思响应的方法是:

  • 压倒
其他一些可能有用的注释:

ServiceStack的内置IOC

您可以将
IDisposable
添加到基类,该基类在服务完成执行后立即被调用,例如,如果要使用RDBMS:

public class FooServiceBase : IService, IDisposable
{
    public IDbConnectionFactory DbFactory { get; set; }

    private IDbConnection db;
    public IDbConnection Db
    {
        get { return db ?? (db = DbFactory.OpenDbConnection()); }
    }

    public object Any(ProductFind request)
    {
        return new FooResponse {
            Result = Db.Id<Product>(request.Id)
        };
    }

    public void Dispose()
    {
        if (db != null) db.Dispose();
    }
}
公共类FooServiceBase:iSeries设备,IDisposable
{
公共IDbConnectionFactory数据库工厂{get;set;}
专用连接数据库;
公共连接数据库
{
获取{return db??(db=DbFactory.OpenDbConnec
public HelloService : Service {
    private readonly IDocumentSession session;
    public HelloService(IDocumentSession session) {
        this.session = session;
    }
}
    public override void Configure(Funq.Container container)
    {
        RequestFilters.Add((httpReq, httpRes, requestDto) =>
            {

                IDocumentSession documentSession = Container.Resolve<IDocumentStore>().OpenSession();
                Container.Register<IDocumentSession>(documentSession);
            });

        ResponseFilters.Add((httpReq, httpRes, requestDto) =>
            {
                using (var documentSession = Container.Resolve<IDocumentSession>())
                {
                    if (documentSession == null)
                        return;

                    if (httpRes.StatusCode >= 400 && httpRes.StatusCode < 600)
                        return;

                    documentSession.SaveChanges();
                }
            });
        var documentStore = new DocumentStore
            {
                ConnectionStringName = "RavenDBServer",
                DefaultDatabase = "MyDatabase",
            }.Initialize();

        container.Register(documentStore);