在C#中为多用户环境生成发票编号

时间:2014-11-19 09:46:32

标签: c# sql-server

我使用Max功能生成发票编号,并在最后一个发票编号上加1。非常直截了当。但我将此应用于多用户环境中遇到问题。因为两个用户同时打开发票窗口都可以获得相同的ID,发票号码应该是第一个出现而不是最后一个,所以我不能使用身份(自动生成ID)作为发票号码。我想在C#...

中为多用户环境窗口表单生成发票编号

另一个问题是两个用户同时访问和更新同一记录会发生什么。

我希望你能理解这个问题。我读到了乐观与悲观锁定,但我需要一个解决方案。那么有人可以回复我吗

3 个答案:

答案 0 :(得分:3)

有一个不同的数据库表,它将存储最大发票号。 当用户打开发票窗口时,运行存储过程

  • 锁定表格
  • 获取当前号码
  • 存储当前的+1号码
  • 解锁表格
  • 返回当前的+1号码

这将确保即使有同时请求,您也将始终获得唯一的发票号。

反面: 1.此存储过程不能同时为多个用户运行,因此在高流量的情况下它将成为瓶颈。 2.发票号码上会有漏洞 - 发票被取消的漏洞。

如果您对此方法不满意,那么必须在保存时生成发票编号,这将是IDENTITY列,但您已提到用户希望在开始时查看发票编号在发票上工作。

更新

我找到了一篇很好的文章,用sp_getapplock详细阐述了上述方法。文章链接为HERE。我建议使用这种方法。

答案 1 :(得分:1)

一般来说问题是你的应用程序提出了不好的要求,而且方法也不合适。

  • 创建发票以进行编辑时,不应分配发票编号,而是将其发送到系统进行交易。这样一来,中止就不会留下空白。

  • 收集发票明细,然后通过存储过程创建插入,将正确的锁定到位。这是微不足道的 - 如果你知道如何锁定相关的表,或者使用app锁定这个SP。

通常,这是存储过程有意义的少数几个地方之一。使用0个订单项生成非帐单发票,以便您的应用程序可以添加详细信息。瞧,问题解决了。如果用户中止,请将发票标记为“已取消”并完成。

答案 2 :(得分:-1)

自动增量列是最佳解决方案。这就是我们在SQL Server中称为Identity列的内容。

如果在您的情况下您无法使用它,您可以在服务器端代码中创建一个线程安全的方法,以根据静态属性生成发票ID。 确保您在单实例模式下使用服务。

static long invoiceId = getMaxFunction();
...
...
public long GenerateInvoiceId()
{
    lock(this)
    {
        return invoiceId++;
    }
}