自托管的wcf服务是否具有状态?

时间:2012-10-01 18:08:45

标签: c# wcf service

我有一个自我托管的WCF服务,我在Silverlight应用程序中使用。我试图在IDictionary对象中存储用户guid列表。每次用户点击服务时,它都会更新用户的日期时间,以便我可以跟踪哪些用户有活动的“会话”。问题是,每次我点击服务时,列表都是空的。它似乎是在每个肥皂请求上删除值?

您是否可以将信息存储在可在多个服务请求中使用的自托管服务中?

提前致谢!

4 个答案:

答案 0 :(得分:2)

它基于每个实例。即默认情况下无会话。

查看this

  

当服务合同设定时   System.ServiceModel.ServiceContractAttribute.SessionMode属性为   System.ServiceModel.SessionMode.Required,那个合同就是这么说的   所有调用(即支持该调用的基础消息交换)   电话)必须是同一个对话的一部分。

答案 1 :(得分:2)

如果您需要在请求之间存储内容,则需要创建具有相应锁定的静态字典,以便在这些请求进入时存储这些请求,或者将此信息存储在数据库(或其他外部存储)中并检查看看每个方法调用中是否存在。这样做的原因是服务类在每个客户端请求上实例化。

由于您已经在用户点击服务时更新了用户日期时间,因此最好通过与datetime字段进行比较来查找是否为活动用户。这具有在每次调用时都准确的优点(如果重新启动服务,字典可能与db不同步)。数据库已经有了处理并发的机制,因此,不是围绕单个对象推出自己的锁定解决方案,而是可以将复杂性推向数据存储。

如果第二个解决方案不够快(并且你已经分析了应用程序并确定它是瓶颈),那么另一个选择是在数据库前使用某种缓存解决方案,以便首先检入数据进入db之前的内存。这个缓存对象需要像字典一样是静态的,并且与任何其他多线程应用程序一样,在锁定方面存在相同的缺陷。

编辑:如果此托管的WCF服务被用作Silverlight应用程序用户的会话存储,并且数据未存储在外部数据存储中,那么您最好确保跟踪它们是否处于活动状态不是任务危急。如上所述,无法保证此数据的正确性。

根据接受的答案,如果您的服务出现故障并需要重新启动(因为这是自托管的,建议您监控故障事件),您必须处置服务主机并实例化新服务主机。可以保留Guid数据的唯一方法是在重新启动之间重新启动服务(假设主机应用程序本身未重新启动,这是一个不同的问题)。

private Dictionary<Guid,string> _session;

Service service = new Service(_session);
_serviceHost = new ServiceHost(service, GetUriMethodInHostApp());

最好是将其存储在外部并按@marc_s建议进行查找。然后这种复杂性消失了。

答案 2 :(得分:1)

您需要更改InstanceContextMode。您可以通过将以下编译器指令添加到WCF类来完成此操作:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

这会将WCF服务作为单个类别运行。有关WCF Instance Context Mode

的更多信息,请参阅

然后你应该使用你的单例对象构建你的服务主机。这是来自一个工作示例的代码,我正在做类似的事情:

            private ServiceHost serviceHost;

            if (serviceHost != null)
                serviceHost.Close();

            if (log.IsInfoEnabled)
                log.Info("Starting WCF service host for endpoint: " + ConfiguredWCFEndpoint);

            // Create our service instance, and add create a new service host from it
            ServiceLayer.TagWCFService service = new ServiceLayer.TagWCFService(ApplicationName,
                ApplicationDescription,
                SiteId,
                ConfiguredUpdateRateMilliseconds);

            serviceHost = new ServiceHost(service, new Uri(ConfiguredWCFEndpoint));

            // Open the ServiceHostBase to create listeners and start listening for messages.
            serviceHost.Open();

正如其他人礼貌地注意到的那样,如果您不熟悉它的工作方式或者它不适合您的特定应用程序,则会产生“后果”。

答案 3 :(得分:1)

如果您不涉及锁定和线程安全的特定代码,可以使用NoSQL数据库存储会话数据,例如MongoDBRavenDB

与@marc_s一样,我认为使用Singleton模式是一件危险的事情,你必须非常谨慎地制作自己的线程安全会话机制。