Mat*_*ino 6 c# database vb.net sql-server asp.net-2.0
我在SQL Server 2005中有一个遗留数据表,它有一个没有身份/自动增量的PK,没有实现它的能力.
因此,我不得不通过ole"SELECT MAX(id)+ 1 FROM table"-before-insert技术手动在ASP.NET中创建新记录.
显然,如果同时插入,这会在ID上产生竞争条件.
什么是优雅地解决比赛碰撞事件的最佳方式?我正在寻找检测碰撞的VB.NET或C#代码的想法,然后通过获得另一个max(id)+ 1来重新尝试失败的插入.可以这样做吗?
思考?评论?智慧?
谢谢!
注意:如果我无法以任何方式更改数据库怎么办?
无法更改数据库模式是很痛苦的。
如果将现有 PK 插入表中,您将收到 SqlException 并显示一条消息,指示违反 PK 约束。捕获此异常并重试插入几次,直到成功。如果您发现碰撞率太高,您可以尝试max(id) + <small-random-int>改为max(id) + 1. 请注意,使用这种方法,您的 id 将会有间隙,并且 id 空间将很快耗尽。
另一种可能的方法是在数据库外部模拟自动增量 id 。例如,创建一个静态整数,Interlocked.Increment每次需要下一个 id 时它都会使用返回值。棘手的部分是将这个静态计数器初始化为合适的值。我会这样做Interlocked.CompareExchange:
class Autoincrement {
static int id = -1;
public static int NextId() {
if (id == -1) {
// not initialized - initialize
int lastId = <select max(id) from db>
Interlocked.CompareExchange(id, -1, lastId);
}
// get next id atomically
return Interlocked.Increment(id);
}
}
Run Code Online (Sandbox Code Playgroud)
显然,后者仅在所有插入的 id 都是通过Autoincrement.NextId单个进程获取时才有效。