答えて
:
session.CreateCriteria(typeof(Customer))
.SetProjection(Projections.Max("Id"))
. UniqueResult();
マックス(ID)+ 1
の顧客から@cus_id選択= MAX(ID)+ 1 'は、IDを生成するために非常に悪い方法です。それがあなたの目標なら、IDを生成する別の方法を見つけてください。
編集:LnDCobraへの答えに:それはあなたが挿入を行うときにあなたが得た最大(ID)がまだMAX(ID)であることを確認するのは難しいので、
それが悪いです。別のプロセスが行を挿入した場合、挿入されるIDは同じになり、挿入が失敗します。 (逆に、挿入が最初に起こった場合、他のプロセスの挿入は失敗します)。
これを防ぐには、他の挿入を禁止する必要があります。パフォーマンスを傷つけるでしょう。
あなただけの書き込みに対してロックすると、他のプロセスは、あなたが得た同じMAX(ID)であるMAX(ID)を取得します。挿入してロックを解除すると、重複するIDが挿入され、失敗します。それともロックしようとします。その場合、あなたを待っています。読んでもロックされていれば、誰もがあなたを待っています。それはまた、書き込みに対してロックした場合、それは重複したIDを挿入しませんが、それはあなたの読み取りとあなたの書き込みを待つん。
は(そして、それはカプセル化を壊す:あなたはRDBMSがそのIDSはなく、それに接続するクライアントプログラムを把握するようにする必要があります。)
一般的に、この戦略はどちらかになります。
*
*が必要破りますそれは
*を動作させるために「配管」コードの束が大幅にパフォーマンス
*または3つすべて
を削減し、それが、遅くあまり堅牢で、ちょうどシーケンスに建てられたのRDBMSのを使用するよりも、コードを維持するために、より多くのハードが必要になりますまたは生成された自動インクリメントID。使用Projection
誰かがより良い方法をidを生成するためにこれを使用し、そうでない場合は理由として、右方向に私を指すことができますか...? –
最善のアプローチは、追加の配列表を作ることです。 シーケンスのターゲットと値を維持できます。
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. 選択最小基準
- 2. 基準の選択
- 3. NHibernateの基準
- 4. 基準ビルドnhibernate
- 5. パーサー選択の基準
- 6. クラウドスパナのインデックス選択基準
- 7. NHibernateの基準エラー
- 8. nhibernateの基準メソッド
- 9. lazyloadのNHibernate基準
- 10. マルチ基準最大Ifステートメント
- 11. インパラ:基準に選択フィールド
- 12. Jボタン選択基準
- 13. NHibernateの基準APIは
- 14. NHibernateの基準と式
- 15. 選択最大行
- 16. 最小最大選択 - チェックボックス
- 17. パンダ - 複数のデータフレーム基準の選択
- 18. マッチングテーブルの最大の選択
- 19. nhibernate結合基準ヘルプ
- 20. NHibernateコンポーネントマッピング(作成基準)
- 21. 最大バージョン値を選択
- 22. 基準ライブラリで選択されたコマンドラインオプション
- 23. 別のデータフレームの基準に基づいて行を選択
- 24. NHibernate QueryOverを使用して列に最大値を持つレコードを選択
- 25. 選択イメージファイル(最大ピック)
- 26. mysqlの行数を基準に基づいて選択する
- 27. 一連の基準に基づいてレコードを選択する
- 28. 選択ソート - 最小/最大のインデックス
- 29. 選択し、最後の2最大
- 30. 基準彼のAndroidアプリケーションのための最小APIレベルを選択する際
この式の戻り値の型は何ですか? – IanT8
オブジェクトです。あなたは、特定の型にキャストするUniqueResultオーバーロードを使用することができます。この場合、あなたはUniqueResult ()は整数にキャストしたいと思います。 –