我们正在使用Castle Windsor作为WCF服务(处理JSON请求/响应)。我们还在数据层中使用实体框架。
当我们使用PerWebRequest
LifeStyle时,它会抛出以下错误:
The server encountered an error processing the request. The exception message is 'HttpContext.Current is null. PerWebRequestLifestyle can only be used in ASP.Net'. See server logs for more details. The exception stack trace is:
at Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule.GetScope() at Castle.MicroKernel.Lifestyle.WebRequestScopeAccessor.GetScope(CreationContext context) at Castle.MicroKernel.Lifestyle.ScopedLifestyleManager.GetScope(CreationContext context) at Castle.MicroKernel.Lifestyle.ScopedLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy) at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden) at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveFromKernelByType(CreationContext context, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveFromKernel(CreationContext context, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveCore(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateConstructorArguments(ConstructorCandidate constructor, CreationContext context) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext context) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context) at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden) at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally) at Castle.MicroKernel.Lifestyle.SingletonLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy) at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden) at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context) at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy) at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(String key, Type service, IDictionary arguments, IReleasePolicy policy) at Castle.MicroKernel.DefaultKernel.Resolve[T](String key, IDictionary arguments) at Castle.Facilities.WcfIntegration.WindsorInstanceProvider.GetInstance(InstanceContext instanceContext, Message message) at System.ServiceModel.Dispatcher.InstanceBehavior.GetInstance(InstanceContext instanceContext, Message request) at System.ServiceModel.InstanceContext.GetServiceInstance(Message message) at System.ServiceModel.Dispatcher.InstanceBehavior.EnsureServiceInstance(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
当我们使用PerWcfOperation
LifeStyle时,它工作正常,但它从数据层返回相同的数据(在我的情况下,它返回相同的UserStatus,除非我在数据层中的每个方法之前初始化_context )。下面是数据层中GET方法的实现:
以下方法在使用PerWebRequest
LifeStyle时提供Web应用程序的预期结果。
public class UserDAL: IUserDAL
{
#region Declaration
private MyDBContainer _context;
#endregion
#region Constructor
public UserDAL()
{
_context = new MyDBContainer();
}
#endregion
#region Get User Status
/// <summary>
/// Get User Status
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public User GetUserStatus(User user)
{
st_User _dbUser = null;
if (user != null && user.UserId > 0)
{
_dbUser = _context.st_User.Where(u => u.User_Id == user.UserId && !u.Is_Deleted).SingleOrDefault();
}
if (_dbUser != null && _dbUser.User_Id > 0)
{
user.LastLoginDate = _dbUser.Last_Login_Date;
user.UserStatus = (UserStatus)Enum.Parse(typeof(UserStatus), _dbUser.User_Status, true);
}
return user;
}
#endregion
}
当我们使用PerWcfSession
LifeStyle时,它会抛出以下错误:
The server encountered an error processing the request. The exception message is 'Could not obtain scope for component MyApp.DAL.UserDAL. This is most likely either a bug in custom IScopeAccessor or you're trying to access scoped component outside of the scope (like a per-web-request component outside of web request etc)'. See server logs for more details. The exception stack trace is:
at Castle.MicroKernel.Lifestyle.ScopedLifestyleManager.GetScope(CreationContext context) at Castle.MicroKernel.Lifestyle.ScopedLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy) at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden) at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveFromKernelByType(CreationContext context, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveFromKernel(CreationContext context, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveCore(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateConstructorArguments(ConstructorCandidate constructor, CreationContext context) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext context) at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context) at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden) at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally) at Castle.MicroKernel.Lifestyle.SingletonLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy) at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden) at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context) at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy) at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(String key, Type service, IDictionary arguments, IReleasePolicy policy) at Castle.MicroKernel.DefaultKernel.Resolve[T](String key, IDictionary arguments) at Castle.Facilities.WcfIntegration.WindsorInstanceProvider.GetInstance(InstanceContext instanceContext, Message message) at System.ServiceModel.Dispatcher.InstanceBehavior.GetInstance(InstanceContext instanceContext, Message request) at System.ServiceModel.InstanceContext.GetServiceInstance(Message message) at System.ServiceModel.Dispatcher.InstanceBehavior.EnsureServiceInstance(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
以下是我们如何使用Castle Windsor LifeStyle:
container.Register(Component.For<IUserDAL>().ImplementedBy<UserDAL>().LifeStyle.PerWcfSession());
对于WCF实施Castle Windsor的最佳方法是等同于PerWebRequest
LifeStyle?请建议
答案 0 :(得分:0)
PerWcfOperation生活方式正是您所发现的。该对象贯穿整个操作。它在一个工作单元中特别有价值,其中注入了UserDAL的业务服务需要进行一些数据库更改,执行更多业务逻辑,然后在最终调用DbContext上的commit之前进行更多业务更改。
我假设您的MyDbContainer有一个您正在使用的私有DbContext实例,这就是您在整个调用过程中遇到共享DbContext的原因。
我可以看到两种方法来修复不需要的行为。首先,你可以让你的生活方式瞬态,因为我在上面的代码中没有看到任何理由,为什么你希望这可以持续wcf操作长度。
另一种解决方案,通常我将采用的方法是让您的数据访问单例并使用IContextFactory(我自己的界面)注入它们,这将为该场合启动适当的生活方式上下文。