I solved my problem.

Previously I used session.Lock(entity, LockMode.Upgrade);, but that throws 
an StaleObjectStateException, but instead, if I used 
session.QueryOver<POCO>().Lock().Upgrade...; it works fine. I suppose that 
the lock was set to late in the first case, so the exception was thrown.

Thanks again for everything :).

El domingo, 17 de abril de 2016, 9:46:39 (UTC-3), Quicoli escribió:
>
> Hi, 
>
> I believe getlastunusedfolio should lock your table and  your transction 
> scope should be something like lock and wait. 
>
> This way the first one in,  lock the access and the subsequent requests 
> keep waiting for the first one to finish... 
>
> This is an idea... 
> Em 17/04/2016 07:18, "Nicolás Mancilla" <[email protected] 
> <javascript:>> escreveu:
>
>> Hello Everyone!
>>
>> I have a question regarding concurrent requests.
>>
>> I have an two entities:
>>
>> class Document {
>>
>> FolioNumber // Long/bigint
>> other_properties...
>>
>> }
>>
>> class FolioRange {
>>
>> CurrentFolio // Long/bigint
>> Start // The first folio in the range
>> End // The last folio in the range
>> IsUsed // When the CurrentFolio >= End
>> DateCreated
>> IsCurrentRange
>>
>> DocumentType
>> RangeStatus 
>>
>> }
>>
>> (Imagine that these are valid POCOs please :) 
>>
>> Every time a Document is inserted to the database, the 
>> Document.FolioNumber is set to the FolioRange.CurrentFolio. The logic is 
>> this:
>>
>> public long GetNextFolioNumber(string documentType, Tenant tenant)
>>         {
>>             // Check if there is a folio range defined
>>             var entity = session.QueryOver<FolioRange>()
>>                 .Where(
>>                     i =>
>>                         i.Tenant.Id == tenant.Id && i.DocumentType == 
>> documentType && i.IsCurrentRange &&
>>                         i.Status == RangeStatus.Enabled)
>>                 .Take(1)
>>                 .SingleOrDefault();
>>             if (entity == null)
>>             {
>>                 return 0;
>>             }
>>  
>>             // Retrieve an unused folio, if there are any
>>             var folio = GetLastUnusedFolio(entity);
>>             if (folio > 0)
>>             {
>>                 return folio;
>>             }
>>  
>>             FolioRange range;
>>  
>>             // If the folio range has no folios left,
>>             // try to change to the newest folio range
>>             if (entity.IsUsed)
>>             {
>>                 log.InfoFormat(
>>                     "The folio range '{0}' has been consumed. Trying to 
>> switch to the next one (if there is one).",
>>                     entity.Id);
>>                 // Update the old folio range to disable it
>>                 entity.IsCurrentRange = false;
>>                 entity.Status = RangeStatus.Disabled;
>>                 session.Update(entity);
>>                 range = session.QueryOver<FolioRange>()
>>                     .Where(
>>                         i =>
>>                             i.Tenant.Id == tenant.Id && i.DocumentType == 
>> documentType &&
>>                             i.CreatedDate > entity.CreatedDate)
>>                     .Take(1)
>>                     .SingleOrDefault();
>>  
>>                 // If there is no newest folio range, return
>>                 if (range == null)
>>                 {
>>                     return 0;
>>                 }
>>  
>>                 log.InfoFormat("Successfully switched to folio range 
>> '{0}'.", entity.Id);
>>                 // If there was a newest folio range, update it.
>>                 range.IsCurrentRange = true;
>>                 range.Status = RangeStatus.Enabled;
>>             }
>>             else
>>             {
>>                 log.InfoFormat("Using folio range '{0}'; Current folio: 
>> {1}", entity.Id, entity.CurrentFolio);
>>                 range = entity;
>>             }
>>  
>>             // Set the current folio as result and increment the current 
>> folio.
>>             folio = range.CurrentFolio;
>>             range.CurrentFolio++;
>>             session.Update(range);
>>             return folio;
>>         }
>>
>>
>> This works well when there is only 1 request, but when there are more than 
>> 1, then there is a race condition when the range.CurrentFolio++ is not 
>> updated and two Documents get created with the same folio number, which is 
>> not allowed.
>>
>>
>> I've tried using session.Lock(range, LockMode.Upgrade), without luck (a 
>> UNIQUE KEY Violation is triggered). The Session.Transaction isolation level 
>> is ReadCommited.
>>
>>
>> I'm using NHibernate 4.0.4 and Nancy 1.4.3.
>>
>>
>> Any suggestions, book references or any reading will be greatly appreciated.
>>
>>
>> Thanks!
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "nhusers" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to [email protected] <javascript:>.
>> To post to this group, send email to [email protected] 
>> <javascript:>.
>> Visit this group at https://groups.google.com/group/nhusers.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.

Reply via email to