![](/img/trans.png)
[英]Avoid duplicates with self-referencing entities in Sql Server table with Entity Framework navigation property
[英]Avoid duplicates in SQL server due the latency
我在C#中有一个类似POS的系统,并且很长一段时间它都没有出现任何问题(它只是一个POS)。 但是现在,使用该系统的是4个POS,并且连接到相同的数据库,并且一个POS的所有销售都转到同一审计(表),而其他所有销售都在该审计中。 所以在这个系统中这是程序
但是使用4个POS时,我意识到有些销售具有相同的票证号,幸运的是,票证ID码不同,因为终端和员工不同,但是如何避免这种情况呢?
编辑1 :每个POS系统都具有双重功能,在一种模式下,POS的销售是集中的,并且在这种模式下,每个POS都会生成连续的票证(就像所有POS一样),在另一种模式下,每个POS都有自己的票证编号,因此我无法使用该身份。
只需使用一个序列来生成下一个票证号。
CREATE SEQUENCE Tickets
START WITH 1
INCREMENT BY 1;
然后每个POS都要做
SELECT NEXT VALUE FOR Tickets;
该序列保证永远不会两次返回相同的数字。
如前所述,如果TicketNumber是连续且唯一的,则听起来像IDENTITY字段是可行的方式。 但是,如果由于某种原因阻止了该操作,或者这一次需要进行太多更改,则可以通过使用Application在ID代码生成过程本身上创建锁,从而将过程本身限制为单线程锁(请参见sp_getapplock和sp_releaseapplock )。 应用程序锁使您可以围绕任意概念创建锁。 意思是,您可以将@Resource
定义为“ generate_id_code”,这将迫使每个调用者等待轮到他们。 它将遵循以下结构:
BEGIN TRANSACTION;
EXEC sp_getapplock @Resource = 'generate_id_code', @LockMode = 'Exclusive';
...current 4 steps to generate the ID Code...
EXEC sp_releaseapplock @Resource = 'generate_id_code';
COMMIT TRANSACTION;
您需要自己管理错误/回滚(如链接的MSDN文档中所述),因此请放入通常的TRY / CATCH中。 但是,这确实可以管理情况。
请注意:应当谨慎使用sp_getapplock
/ sp_releaseapplock
。 应用程序锁绝对可以非常方便(例如在这种情况下),但是只有在绝对必要时才应使用它们。
如果可能的话,我强烈建议您放弃当前的方法,而改用GUID PK。
但是,我意识到在某些情况下无法进行重新设计(我们在遗留数据库中描述的场景完全相同)。
在这种情况下,可以结合使用UPDLOCK表提示和insert命令安全地获取最大值,并在需要时使用OUTPUT INSERTED
功能将新的主键值检索到局部变量中:
DECLARE
@PK Table (PK INT NOT NULL)
INSERT
INTO Audit (
TicketNumber,
Terminal,
Date,
EmployeeCode,
Client,
IDCode,
... other fields )
/* Record the new PK in the tablevariable */
OUTPUT INSERTED.TicketNumber INTO @PK
SELECT IsNull(MAX(TicketNumber), 0) + 1,
@Terminal,
@Date,
@EmployeeCode,
@Client,
@IDCode,
... other values
FROM Audit WITH (UPDLOCK)
DECLARE @TicketNumber INT
/* Move the new PK from the local tablevariable into a local variable for subsequent use */
SELECT @TicketNumber = PK
FROM @PK
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.