回答
使用Projection:
session.CreateCriteria(typeof(Customer))
.SetProjection(Projections.Max("Id"))
. UniqueResult();
MAX(ID)+ 1 '選擇@cus_id =最大客戶(ID)+ 1' 是生成ID的非常糟糕的方式。如果這是您的目標,請找到另一種生成ID的方法。
編輯:在回答LnDCobra:
這是不好的,因爲它很難確保你得到了最大(ID)仍然最大(ID),當你插入。如果另一個進程插入一行,您的插入將具有相同的ID,並且插入將失敗。 (或者相反,如果您的插入先發生,則其他進程的插入將失敗。)
爲了防止出現這種情況,您必須防止其他任何插入/使您的get和後續插入原子,這通常意味着鎖定表,會損害表現。
如果只鎖定對寫入,其他的進程得到最大(ID),這是相同的MAX(ID),你知道的。你做你的插入和釋放鎖,它插入一個重複的ID並失敗。或者它也試圖鎖定,在這種情況下它會等待你。如果你鎖定閱讀,每個人都在等你。如果對鎖定也寫,那麼就不會插入重複的ID,但它並等待您的讀取和寫入的。
(而且它打破封裝:你應該讓RDBMS弄清楚它的ID,而不是連接到它的客戶端程序。)
一般情況下,這種策略之一:
*打破
*需要一串「管道」代碼,使其工作
*顯著降低性能
*或全部三個
,它會比較慢,不太可靠,並且需要更多的努力維護的代碼比只使用內置的序列的RDBMS或生成自動增量ID。
有人點我在正確的方向,爲什麼不利用這個生成的ID,如果有一個更好的辦法...? – 2010-11-05 10:28:41
最好的辦法就是讓更多的序列表。 您可以在哪裏維護序列目標和值。
public class Sequence : Entity
{
public virtual long? OwnerId { get; set; }
public virtual SequenceTarget SequenceTarget { get; set; }
public virtual bool IsLocked { get; set; }
public virtual long Value { get; set; }
public void GenerateNextValue()
{
Value++;
}
}
public class SequenceTarget : Entity
{
public virtual string Name { get; set; }
}
public long GetNewSequenceValueForZZZZ(long ZZZZId)
{
var target =
Session
.QueryOver<SequenceTarget>()
.Where(st => st.Name == "DocNumber")
.SingleOrDefault();
if (target == null)
{
throw new EntityNotFoundException(typeof(SequenceTarget));
}
return GetNewSequenceValue(ZZZZId, target);
}
protected long GetNewSequenceValue(long? ownerId, SequenceTarget target)
{
var seqQry =
Session
.QueryOver<Sequence>()
.Where(seq => seq.SequenceTarget == target);
if (ownerId.HasValue)
{
seqQry.Where(seq => seq.OwnerId == ownerId.Value);
}
var sequence = seqQry.SingleOrDefault();
if (sequence == null)
{
throw new EntityNotFoundException(typeof(Sequence));
}
// re-read sequence, if it was in session
Session.Refresh(sequence);
// update IsLocked field, so we acuire lock on record
// configure dynamic update , so only 1 field is being updated
sequence.IsLocked = !sequence.IsLocked;
Session.Update(sequence);
// force update to db
Session.Flush();
// now we gained block - re-read record.
Session.Refresh(sequence);
// generate new value
sequence.GenerateNextValue();
// set back dummy filed
sequence.IsLocked = !sequence.IsLocked;
// update sequence & force changes to DB
Session.Update(sequence);
Session.Flush();
return sequence.Value;
}
OwnerId - 當您需要基於某種所有者維護同一個實體的不同序列時。例如,你需要維護合同內編號爲文檔,然後OwnerId will be = contractId
- 1. 選擇的Nhibernate標準
- 2. 選擇MAX()加入NHibernate
- 3. NHibernate:同時選擇MAX值
- 4. 選擇MAX(ID)mysql
- 5. NHibernate的標準查詢 - 選擇獨特
- 6. 使用nhibernate在另一條標準內選擇標準
- 7. NHibernate/LINQ在子查詢中選擇MAX?
- 8. 選擇MAX()和相應的ID
- 9. NHibernate的標準
- 10. Java標準的API - 從表中選擇*,其中id = id
- 11. 選擇MAX日期加上ID值
- 12. 選擇MAX時間戳和JPA2標準API
- 13. id與類選擇基準
- 14. NHibernate的選擇與SqlFunction列,按照相同的標準組
- 15. NHibernate標準查詢 - 選擇加入實體的區別
- 16. NHibernate選擇符合標準的最新記錄
- 17. 選擇與標準
- 18. Bintprog,選擇標準
- 19. Forumla NHibernate的標準
- 20. Nhibernate和max(uniqueID)作爲三個標準之一?
- 21. SQL - 選擇+ MAx()
- 22. 選擇MAX值
- 23. NHibernate的:標準/子標準投影
- 24. NHibernate的QueryOver語法可以選擇一個SqlFunction的MAX()嗎?
- 25. 選擇標記ID
- 26. 選擇使用波輪選擇標準
- 27. TSQL隨機選擇選擇標準
- 28. NHibernate的選擇
- 29. SQL到Nhibernate標準
- 30. NHibernate標準問題
這個表達式的返回類型是什麼? – IanT8 2010-05-11 03:14:19
一個對象。您可以使用UniqueResult重載將它轉換爲特定類型。在這種情況下,你會想UniqueResult (),以將其轉換爲整數。 –
2011-01-27 23:54:54