The service layer is seperated into command and query side and each side has their handlers.

The following configuration is used

// EF context
_container.RegisterPerWcfOperation<MyDbContext, MyDbContext>();
_container.RegisterManyForOpenGeneric(typeof(IHandler<>),
    ApplicationAssemblies);

// many more regs but nothing special

SimpleInjectorServiceHostFactory.SetContainer(_container);

and the needed markup settings:

Factory="SimpleInjector.Integration.Wcf.SimpleInjectorServiceHostFactory, SimpleInjector.Integration.Wcf"

throws the following exception:

WCF scopes can not be nested.

I think the error occurs in

internal WcfOperationScope BeginScope()

of the WcfOperationScopeManager implementation.

Some background informations:

  • WinForm application
  • execution of the QueryClient is done with a backgroundworker
  • I'm using Simple Injector version 2.2.3
  • Global.asax which builds the container
  • hosted in IIS
  • each .svc has its markup set to use SimpleInjectorFactory
  • wsHttpBinding with certificate and custom UserNamePasswordValidator
  • each endpoint configuration has all needed values set to 2147483647.

The error occurs when I execute two loading request fast consecutively so the first is not finished and the second one occurs.

有帮助吗?

解决方案

This is a known problem with Simple Injector 2.2.3 for some WCF configurations. Some WCF configurations force a second call to IInstanceProvider.GetInstance. The SimpleInjectorInstanceProvider.GetInstance methods call into the internal BeginScope method, which is limited to one scope.

There are two solutions:

First solution is to upgrade to the latest Simple Injector WCF Integration package. The 2.3.0 release of the WCF integration package fixed this issue.

Second solution is to not use the Per WCF Operation at all, but use the lifetime scope (which works similar as the Per WCF Operation lifestyle). This is especially a good solution in your case, since you use command handlers and query handlers. In other words, your WCF service will probably consist of just two WCF operations. This makes it very easy to wrap those two methods in a lifetime scope, without needing to worry the code has to be added to all other operations in the service (since your service won't get any more operations). Your operation will look like this:

[OperationContract]
public object Execute(dynamic command)
{
    Type commandHandlerType = typeof(ICommandHandler<>)
        .MakeGenericType(command.GetType());

    using (Bootstrapper.BeginLifetimeScope())
    {
        dynamic commandHandler = Bootstrapper.GetInstance(commandHandlerType);

        commandHandler.Handle(command);
    }

    return command;
}

Of course, all registrations made with Per WCF Operation should be changed to Lifetime scope:

_container.Register<MyDbContext, MyDbContext>(new LifetimeScopeLifestyle());
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top