我们正在开发基于WCF的系统。 在此过程中,我们试图锁定一些数据,使其不被多个用户修改。 所以我们决定建立一个数据结构,包含执行锁定逻辑的必要信息(例如存储锁定对象的ID)
我们遇到的问题是在会话之间保持数据。 反正我们可以避免执行昂贵的数据库调用吗? 我不知道我们怎么能在WCF中这样做,因为它只能在打开的会话期间持久保存数据(在内存中)。
服务实现类的静态成员在会话和调用之间共享。
Jimmy McNulty说,一种选择是使用静态成员。 我有一个WCF服务,它根据用户指定的IP地址打开网络连接。 我的服务配置为PerCall服务实例模式。 在每个会话中,我检查静态数据结构以查看是否已为指定的IP地址打开网络连接。 这是一个例子。
[ServiceContract]
public interface IMyService
{
[OperationContract]
void Start(IPAddress address);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class MyService : IMyService
{
private static readonly List<IPAddress> _addresses = new List<IPAddress>();
public void Start(IPAddress address)
{
lock(((ICollection)_addresses).SyncRoot)
{
if (!_addresses.Contains(address)
{
// Open the connection here and then store the address.
_addresses.Add(address);
}
}
}
}
按照配置,每次调用Start()都会在其自己的服务实例中进行,并且每个实例都可以访问静态集合。 由于每个服务实例都在一个单独的线程中运行,因此必须同步对集合的访问。
与在多线程编程中完成的所有同步一样,请确保最大限度地减少锁中花费的时间。 在所示的示例中,一旦第一个调用者获取锁定,所有其他调用者必须等到锁定被释放。 这适用于我的情况,但可能不适合你的。
另一种选择是使用单一服务实例模式而不是PerCall服务实例模式。
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService : IMyService
{ ... }
不过,从我读过的所有内容来看,PerCall似乎更灵活。
您可以按照此链接查看两者之间的差异。
并且不要忘记实现您的服务的类就是 - 一个类。 它像所有C#类一样工作。 您可以添加静态构造函数,属性,事件处理程序,实现其他接口等。
也许像velocity这样的缓存框架会帮助你解决问题。
创建第二个类并将其InstanceContextMode设置为single并将所有昂贵的方法移动到那里,然后在原始类中使用该方法。