回答
使用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. 选择MAX(ID)mysql
- 2. 选择MAX()加入NHibernate
- 3. NHibernate的标准查询 - 选择独特
- 4. 选择MAX()和相应的ID
- 5. Java标准的API - 从表中选择*,其中id = id
- 6. 选择MAX时间戳和JPA2标准API
- 7. id与类选择基准
- 8. NHibernate的选择与SqlFunction列,按照相同的标准组
- 9. 选择与标准
- 10. Bintprog,选择标准
- 11. NHibernate标准查询 - 选择加入实体的区别
- 12. NHibernate选择符合标准的最新记录
- 13. Forumla NHibernate的标准
- 14. SQL - 选择+ MAx()
- 15. 选择使用波轮选择标准
- 16. TSQL随机选择选择标准
- 17. NHibernate标准问题
- 18. 选择计数MAX()()
- 19. 休眠标准ManyToMany选择
- 20. Grails - 标准,独家选择
- 21. 休眠标准 - 从选择
- 22. NHibernate的标准,由物业
- 23. NHibernate的标准问题
- 24. NHibernate的 “SELECT ... FROM(SELECT ...” 标准
- 25. NHibernate的标准API预测
- 26. NHibernate的多对多标准
- 27. NHibernate的或标准查询
- 28. NHibernate的标准逆转LIKE
- 29. nhibernate的标准方法
- 30. 加入标准NHibernate的
这个表达式的返回类型是什么? – IanT8 2010-05-11 03:14:19
一个对象。您可以使用UniqueResult重载将它转换为特定类型。在这种情况下,你会想UniqueResult (),以将其转换为整数。 –
2011-01-27 23:54:54