将RavenDB与ServiceStack一起使用 [英] using RavenDB with ServiceStack

查看:108
本文介绍了将RavenDB与ServiceStack一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了Phillip Haydon的这篇帖子,内容涉及在ServiceStack中使用NHibernate/RavenDB.
每当我需要这样的数据库内容时,我都看不到获取IDocumentStore和打开新会话的意义:

I read this post by Phillip Haydon about how to use NHibernate/RavenDB with ServiceStack.
I don't see the point about getting the IDocumentStore and open new session every time i need something from the db like this:

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*/};
        }
    }
}

为什么我不能为每个请求只使用一个会话,而当请求结束时,请根据响应状态提交更改或将其回滚?

Why cant i just use one session per request and when the request is ended, commit the changes or roll them back according to the response status?

如果我的方法很好,那我该怎么执行呢? 这是我的尝试:

If my approach is fine, than how can i implement it? here is my attempt:

我创建了此类:

    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 FooService : ServiceBase<Foo>
{
    public IRavenSession RavenSession { get; set; }

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

        return new FooResponse {/*Object init*/};
    }
}

但是我仍然需要找到一种方法来知道何时结束提交/回滚更改的请求.
我发现的最好方法是使用ResponseFilters:

but i still need to find a way to know when the request is ended for commit/rollback the changes.
the best way i found is by using ResponseFilters:

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...
    }
}

我确信有更好的方法可以做到这一点,但是如何呢?

I am sure that there is a better way to do this but how?

推荐答案

我刚刚将其包含在AppHost的Configure方法中

I just included this on the Configure method for the AppHost

var store = new DocumentStore()
{
    Url = "http://127.0.0.1:8080",
    DefaultDatabase = "Test"
}.Initialize();

container.Register(store);

container.Register(c => c.Resolve<IDocumentStore>().OpenSession()).ReusedWithin(ReuseScope.Request);

您可以将其放在模块上并对其进行初始化.

You can put it aside on module and initialize it.

然后在您的服务中只需添加一个接受IDocumentSession的构造函数

Then in your services just add a constructor that accepts IDocumentSession

public HelloService : Service {
    private readonly IDocumentSession session;
    public HelloService(IDocumentSession session) {
        this.session = session;
    }
}

你很好.

这篇关于将RavenDB与ServiceStack一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆