gpt4 book ai didi

c# - 如何按ID自动重启列增量?

转载 作者:行者123 更新时间:2023-11-30 16:50:59 24 4
gpt4 key购买 nike

我们正在开发供小型企业使用的 Multi-Tenancy 系统,需要为其客户生成发票。出于显而易见的原因,基本上每个租户都希望自己的发票编号序列彼此独立生成。所以第一个租户可以有发票 1、2、3,第二个租户可以有相同的发票,因为他们是独立的企业并且彼此一无所知。

我们使用 Entity Framework 7 作为 ORM,使用 SQL 2014 作为数据库。我们需要一种方法来生成这些发票编号,而不会在高并发负载下为同一租户意外重复。最初在 EF 中,我们只是取发票列的最大值,其中租户 = 当前租户 ID,然后将其加 1,但在压力测试之后,它为该租户创建了很多重复的发票编号。触发器对此更好吗?序列?我不确定下一步该去哪里。

这是描述我们情况的简化表格布局。请注意最后一个表格,每个租户的发票编号需要如何重新启动。这就是我们要实现的目标

+----------+-------------+
| TenantID | TenantName |
+----------+-------------+
| 5 | ABC Company |
| 6 | XYZ Corp |
+----------+-------------+
+----------+------------+----------------+
| TenantID | CustomerID | CustomerName |
+----------+------------+----------------+
| 5 | 2 | Alpa Customer |
| 5 | 5 | Beta Customer |
| 6 | 3 | Delta Customer |
| 6 | 4 | Omega Customer |
+----------+------------+----------------+

+----------+------------+-----------+-------------------------------------------------------+
| TenantID | CustomerID | InvoiceID | InvoiceNumber(this one needs to restart per tenant) |
+----------+------------+-----------+-------------------------------------------------------+
| 5 | 2 | 1 | 1 |
| 5 | 2 | 7 | 2 |
| 5 | 5 | 2 | 3 |
| 5 | 5 | 4 | 4 |
| 5 | 5 | 5 | 5 |
| 6 | 3 | 8 | 1 |
| 6 | 4 | 3 | 2 |
| 6 | 4 | 6 | 3 |
+----------+------------+-----------+-------------------------------------------------------+

基于@ERIKE 的回答我最终在 TenantID 和 InvoiceNumber 周围添加了一个唯一约束,然后我取发票号的最大值并将其加一并尝试插入。这是围绕在 C# 中的 do while 循环。每当出现唯一约束错误时,它都会重试

bool retryInsert;
do
{
try
{
retryInsert = false;
var invNo = (db.tbl_Invoice
.Where(t => t.TenantID == invoice.TenantID)
.Max(t => t == null ? 0 : t.InvoiceNumber)
) + 1;

invoice.InvoiceNumber = invNo;
db.tbl_Invoice.Add(invoice);
db.SaveChanges();
}

catch (DbUpdateException ex)
{
retryInsert = false;
var sqlexception = ex.InnerException as SqlException;
if (sqlexception != null)
{
if (sqlexception.Errors.OfType<SqlError>()
.Any(se => se.Number == 2627))
{
retryInsert = true;
}

else throw ex;
}
}
} while (retryInsert);

return invoice;

最佳答案

为了支持每秒最高的交易,我相信你最好的答案是在发票表中的(租户ID,发票ID)上放置一个唯一索引并进行并发插入,然后在唯一键的情况下违规,重试。

我基于几年前读到的一篇关于在这种情况下实现最高吞吐量的文章。

无论如何,我强烈建议不要为每个租户提供一张 table 。您可能会研究序列,但我不确定每个租户有一个序列是否合理。

每个租户一行的“最后一张发票”表可以工作:

UPDATE dbo.TenantLastInvoice
SET
LastInvoiceID = LastInvoiceID + 1,
@InvoiceID = InvoiceID
WHERE TenantID = 123;

我不是 100% 确定您是否需要锁定提示,您可以考虑 ROWLOCKUPDATELOCK,如果所有其他方法都失败,READPAST(如果没有发生更新则重试)。

不要指望能够完美地避免偶尔跳过 ID。一个人要么容忍碰撞的可能性(完全 Not Acceptable ),要么容忍在某些边缘情况下跳过 ID(烦人,但不是世界末日),这似乎是一个难以接受的事实。

关于c# - 如何按ID自动重启列增量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34258820/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com