1

I have to issue many invoices for which i use hangfire jobs. Each invoice number has to be unique. I have got this method in my NumberSequenceRepository which should prevent from using same invoice number twice:

static object padlock = new object();

public InvoiceNumberSequence GetNextInvoiceNumber(DateTime forDate)
{
    lock (padlock)
    {
        var seq = db.InvoiceNumberSequence.Single();

        seq.CurrentNumber++;

        db.SaveChanges();

        return seq;
    }
}

Yet it looks like Hangfire ignores lock statements (also tried Mutex but with no results) and numbers do repeat. Why is that?

Krzysztof
  • 498
  • 5
  • 23
  • 2
    Could you use `DisableConcurrentExecution` attribute on your method? – DavidG Aug 14 '17 at 08:54
  • Not really, because there can be a lot of invoices and it can take a significant amount of time. Acquiring invoice number is the only critical section in the whole process. Then again I've tried this Attribute and it doesn't seem to work.. – Krzysztof Aug 14 '17 at 08:58
  • 1
    Hangfire can't just "ignore" lock statements, a lock is a lock, there must be something else going on. Are you running multiple Hangfire server instances? Note the `lock` statement only works within the same app domain. Also why are you re-inventing something that can be easily accomplished via a database autoincremented PK which handles concurrency for you? – Saeb Amini Aug 14 '17 at 09:03
  • Hangfire runs in Azure as a part of WebApp (ASP.NET MVC) and there is only one instance of it. But the same thing happens on my local machine. I can't use database for this because sequence has to have custom format and be resetted after configurable amount of time. – Krzysztof Aug 14 '17 at 09:14
  • 1
    Why not just have the DB be responsible for generating the invoice numbers once you insert the data? I'm not understanding why you're trying to generate it upfront. Another approach might be to not run the sequence number through a single row in the DB, but to have a table where you can pregenerate a bunch of invoice numbers and then allocate it to your invoice. – Cyberwiz Aug 14 '17 at 13:29
  • Yup, that is true. But at this point it's my curiosity. Why the concurrent calls? Either: a) Hangfire doesn't use threads (processes maybe?) b) locks don't work :) c) db.SaveChanges() doesn't really commit changes to db (deffered update?) – Krzysztof Aug 20 '17 at 18:16
  • Hangfire server sure can run in multiple processes (and even on multiple servers), but the issue is EF not saving changes. Refer to https://stackoverflow.com/questions/14857813/entity-framework-savechanges-not-updating-the-database – Alex Skalozub Sep 18 '17 at 13:12

0 Answers0