我正在尝试在我的WCF应用程序中实现一个每请求会话模型,并且我已经阅读了关于这个主题的无数文档,但看起来还没有完整的演示.我实际上遇到过一些非常有用的文章,例如:
但是这些都来自NHibernate和Ninject没有WCF特定实现的旧时代,因此他们通过实现他们的自定义服务提供程序等来实现我所需要的.因为Ninject和NHibernate现在都支持WCF,所以我希望保持一致通过使用他们的模块,但我最终在这里......
基本设置和流程应该是这样的:
我最初的问题是我无法访问wcf生命周期来处理我的绑定.在深入挖掘ninject代码之后,我设法将我的方法挂钩到ServiceHost的Opening/Closing事件而没有太大变化,但后来我无法访问OperationContext,因为它是线程静态的.
后来我尝试启用asp.net兼容性并使用Application_BeginRequest和Application_EndRequest,它看起来非常有前景,但我不认为这是最好的解决方案,因为我应该将东西绑定到服务实例,而不是http请求.
有没有人使用ninject的内置wcf扩展库实现这一目标?或者我可能做错什么的任何想法?
我在教程中看到了如下代码EF code first,MVC并StructureMap创建了一个Context Per Request模式:
protected void Application_Start()
{
...
initStructureMap();
}
private static void initStructureMap()
{
ObjectFactory.Initialize(x =>
{
x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Context());
x.For<IFirstEntity>().Use<FirstEntity>();
x.For<ISecondEntity>().Use<SecondEntity>();
x.For<IThirdEntity>().Use<ThirdEntity>();
});
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
}
protected void Application_EndRequest(object sender, EventArgs e)
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return ObjectFactory.GetInstance(controllerType) as Controller;
}
}
Run Code Online (Sandbox Code Playgroud)
FirstEntity,SecondEntity...所有需要IunitOfWork在他们的构造函数中.
正如你所看到的那样它只是HttpContextScoped()用于Context其他人而不是在EndRequest …
structuremap entity-framework session-per-request asp.net-mvc-3
我用NHibernate编写了一个C#MVC 3作为ORM,我在大多数页面加载时抛出了一些奇怪的异常.他们似乎主要涉及闭门会议等,我已经检查了大多数常见问题,但没有找到帮助.一些例外包括:
[[NHibernate.Util.ADOExceptionReporter]] : System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)
[[NHibernate.Transaction.AdoTransaction]] : Begin transaction failed
System.Data.SqlClient.SqlException (0x80131904): The server failed to resume the transaction. Desc:3b00000006.
[[NHibernate.Transaction.AdoTransaction]] : Commit failed
System.NullReferenceException: Object reference not set to an instance of an object.
[[NHibernate.Transaction.AdoTransaction]] : Commit failed
System.Data.SqlClient.SqlException (0x80131904): The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
[[NHibernate.Util.ADOExceptionReporter]] : System.InvalidOperationException: The transaction is either not associated with the current …Run Code Online (Sandbox Code Playgroud) c# nhibernate asp.net-mvc session-management session-per-request
正如我在标题中所说,我想实现每个Web请求的会话.我的会话提供程序配置如下(我对改变此conf不感兴趣.)
public class SessionProvider
{
public static SessionProvider Instance { get; private set; }
private static ISessionFactory _SessionFactory;
static SessionProvider()
{
var provider = new SessionProvider();
provider.Initialize();
Instance = provider;
}
private SessionProvider()
{
}
private void Initialize()
{
string csStringName = "ConnectionString";
var cfg = Fluently.Configure()
....ommiting mappings and db conf.
.ExposeConfiguration(c => c.SetProperty("current_session_context_class", "web"))
.BuildConfiguration();
_SessionFactory = cfg.BuildSessionFactory();
}
public ISession OpenSession()
{
return _SessionFactory.OpenSession();
}
public ISession GetCurrentSession()
{
return _SessionFactory.GetCurrentSession();
}
}
Run Code Online (Sandbox Code Playgroud)
在Global.asax.cs中,我有以下与每个Web请求的会话相关的代码.
private static ISessionFactory …Run Code Online (Sandbox Code Playgroud) nhibernate asp.net-mvc fluent-nhibernate session-per-request
我想我的工作单元可能会在我的架构中设置错误.这是我目前拥有的(缩进显示顺序):
HttpRequest.Begin()
UnitOfWork.Begin()
Session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);
Run Code Online (Sandbox Code Playgroud)
在这里,我使用NHibernate调用各种服务来执行crud.当我想对数据库进行更改(更新/保存)时,我调用此代码:
using (var transaction = unitOfWork.Session.BeginTransaction())
{
try
{
// These are just generics
ret = (Key)unitOfWork.Session.Save(entity);
transaction.Commit();
rb.unitOfWork.Session.Clear();
}
catch
{
transaction.Rollback();
rb.unitOfWork.Session.Clear();
rb.unitOfWork.DiscardSession();
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
当HttpRequest结束时,我执行以下步骤:
UnitOfWork.Commit()
Transaction.Commit() // This is my sessions transaction from the begin above
Run Code Online (Sandbox Code Playgroud)
我遇到了能够回滚大批量进程的问题.因为我在我的CRUD层中提交我的事务,如上所示,我的事务不再处于活动状态,当我尝试在UnitOfWork中回滚时,由于事务已经提交,它什么都不做.我在我的CRUD层中提交代码的原因是我可以尽可能快地保留我的数据,而不会长时间锁定数据库.
在上述情况下采取的最佳行动方案是什么?我是否只进行了不提交批处理作业的特殊CRUD操作,只是在我的工作结束时处理提交,或者我的逻辑是否与我的UnitOfWork和Session Per Request有关?有什么建议?