我希望在需要之前找到一些关于实现获取一堆 id 值(如数据库标识值)的最佳方法的建议。我有许多需要唯一 id(int)的类,我想做的是获取下一个可用的 id(每个类,每个服务器)并将其缓存在本地准备就绪。当一个 id 被拿走时,我想让下一个准备好,等等。
我已经制作了一些代码来演示我正在尝试做的事情。代码很糟糕(它应该包含锁等),但我认为它明白了这一点。丢失奇数 ID 不是问题 - 重复 ID 是(问题)。我对 GetNextIdAsync 的胆量很满意——它调用了一个 proc
this.Database.SqlQuery<int>("EXEC EntityNextIdentityValue @Key",
new SqlParameter("Key", key))).First();
在 SQL Server 上使用 sp_getapplock 确保每个返回值都是唯一的(并且是增量的)。
static class ClassId
{
static private Dictionary<string, int> _ids = new Dictionary<string,int>();
static private Dictionary<string, Thread> _threads = new Dictionary<string,Thread>();
static ClassId()
{
//get the first NextId for all known classes
StartGetNextId("Class1");
StartGetNextId("Class2");
StartGetNextId("Class3");
}
static public int NextId(string key)
{
//wait for a current call for nextId to finish
while (_threads.ContainsKey(key)) { }
//get the current nextId
int nextId = _ids[key];
//start the call for the next nextId
StartGetNextId(key);
//return the current nextId
return nextId;
}
static private void StartGetNextId(string key)
{
_threads.Add(key, new Thread(() => GetNextIdAsync(key)));
_threads[key].Start();
}
static private void GetNextIdAsync(string key)
{
//call the long running task to get the next available value
Thread.Sleep(1000);
if (_ids.ContainsKey(key)) _ids[key] += 1;
else _ids.Add(key, 1);
_threads.Remove(key);
}
}
我的问题是 - 在我需要它之前始终拥有我需要的下一个价值的最佳方法是什么?班级应该如何安排,锁应该在哪里?例如,GetNextIdAsync() 中的锁添加新线程但不启动它并将 StartGetNextId() 更改为调用 .Start()?