我创建了一个WCF服务,它从数据库中读取并发回结果。出于性能原因,我想在服务启动时缓存表(这在Windows服务OnStart中发生)。但是在WCF中没有构造函数这样的东西(对吧?)所以我想出的最好的事情是创建一个Init()函数并调用如下:
protected override void OnStart(string[] args)
{
mServiceHost = new ServiceHost(typeof(DLSService.DLSService), new Uri("http://localhost:8000/DLS"));
mServiceHost.AddServiceEndpoint(typeof(DLSService.IDLSService), new BasicHttpBinding(), "ServicesHost");
((DLSService.DLSService)mServiceHost.SingletonInstance).Init();
mServiceHost.Open();
}
但是使用SingletonInstance并将其转换为正确的类型似乎并不适合我。 是否有更优雅的方法来实现WCF中的构造函数?
答案 0 :(得分:3)
建议的最佳做法是在WCF中使用 per-call 激活模型,并使服务完全无状态。
这意味着:每次客户端发出请求时,在服务器端,将创建服务实现类的实例,将进行所请求的服务调用,然后再次销毁服务类。 / p>
因此,将初始化代码放入服务实现类构造函数中是一个非常糟糕的主意 - 它将针对每个单个请求执行。
您可以做的是拥有某种逻辑(在您的服务类中,或者某些支持代码,例如某种管理界面),这些逻辑会将您要缓存的表加载到持久缓存中,例如:像AppFabric缓存之类的东西。完成后,处理请求的多个服务实例可以使用该公共缓存来获得更好的性能。
答案 1 :(得分:3)
这可以通过memoization库来解决,例如MbCache。我们正在做你正在寻找的东西;在应用程序启动时,我们调用我们要缓存的每个服务操作,并且MbCache缓存连续调用的结果(即没有数据库往返以获得结果),直到缓存过期。
MbCache确实具有公平的复杂性,但一旦运行它就可以很好地处理我们的所有缓存逻辑。
答案 2 :(得分:1)
您可以使用IInstanceProvider
界面来创建服务,请阅读this文章以获取更多信息。
以下是代码示例:
public class CustomInstanceProvider:IInstanceProvider
{
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
return new DLSService.DLSService();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
var mServiceHost = new ServiceHost(typeof(DLSService.DLSService), new Uri("http://localhost:8000/DLS"));
mServiceHost.AddServiceEndpoint(typeof(DLSService.IDLSService), new BasicHttpBinding(), "ServicesHost");
foreach (var channelDispatcher in mServiceHost.ChannelDispatchers.OfType<ChannelDispatcher>())
{
foreach (var endpointDispatcher in channelDispatcher.Endpoints)
{
endpointDispatcher.DispatchRuntime.InstanceProvider = new CustomInstanceProvider();
}
}
mServiceHost.Open();
答案 3 :(得分:0)
使用framework 4.5,您可以在服务实现代码中使用配置函数:
http://msdn.microsoft.com/en-us/library/hh205277(v=vs.110).aspx