顺序(无间隙)发票编号创建

时间:2016-07-07 11:46:35

标签: c# asp.net-mvc-4 concurrency sql-server-2012 entity-framework-5

我们已经为Billing系统实施了一个web应用程序。我有一个字符串列来存储发票号。这一栏必须禁止数字之间的差距。

  Id     InvoiceNumber(Desired)    InvoiceNumber(Actual)
   1         001                        001
   2         002                        002
   3         003                        005

在伪代码中

using (TransactionScope _ts = new TransactionScope())
{

     var _lastGeneratedRecDetails = _db.StudentReceipts
                                            .Where(r => r.Status == true
                                                     && r.StudentRegistration.StudentWalkInn.CenterCode.Id == _centreCodeId
                                                     && EntityFunctions.TruncateTime(r.DueDate.Value) >= _startDate.Date
                                                     && EntityFunctions.TruncateTime(r.DueDate.Value) <= _endDate.Date)
                                            .AsEnumerable()
                                            .OrderByDescending(x => x.ReceiptNo != null ? Int32.Parse(x.ReceiptNo) : 0)
                                            .FirstOrDefault();

       var _newReceiptNo=Convert.ToInt32(_lastGeneratedRecDetails.ReceiptNo) + 1
     ....
     ....
     _ts.complete();

}

问题一切都运行正常,直到50thinvoice,之后系统突然跳过2张发票并生成Invoice 52.我们调查了系统状态,发现系统没有被外部篡改,我们也推断出没有人从工作台访问数据库。这是一个重大问题,因为它也有法律后果。

我已经完成了几项研究,并指出了以下解决方案

1.在事务期间锁定整个表并在完成后将其释放。我担心的是如果在发布锁之前服务器崩溃/互联网连接断开连接会发生什么

  using (Entities entities = new Entities())
  using (TransactionScope scope = new TransactionScope())
  {
      //Lock the table during this transaction
       entities.Database.ExecuteSqlCommand("SELECT TOP 1 KeyColumn FROM     MyTable WITH (TABLOCKX, HOLDLOCK)");

      //Do your work with the locked table here...

      //Complete the scope here to commit, otherwise it will rollback
      //The table lock will be released after we exit the TransactionScope block
      scope.Complete();
  }

2.使用storedprocedure生成invoicenumber,程序将是这样的事情

START TRANSACTION;
SELECT number FROM invoice_numbers WHERE name='main' FOR UPDATE;

assign the number to the invoice and set its status to finalized;

UPDATE invoice_numbers SET number = number + 1 WHERE name='main';
COMMIT;

如果有人能帮助我选择哪一个可能是正确的解决方案,那将是非常有帮助的

0 个答案:

没有答案