将RavenDB与ServiceStack一起使用
我读了Phillip Haydon关于如何将NHibernate/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
我看不出每次我需要从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中的响应
在中反思响应的方法是:
- 或
- 压倒
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);