Tôi có thể sử dụng Tiêu chí để thực thi lệnh t-sql để chọn giá trị lớn nhất cho một cột trong bảng không?Tiêu chí Nhibernate: 'chọn tối đa (id) ...'
'chọn @cus_id = max (id) + 1 từ khách hàng'
Tạ
Ollie
Tôi có thể sử dụng Tiêu chí để thực thi lệnh t-sql để chọn giá trị lớn nhất cho một cột trong bảng không?Tiêu chí Nhibernate: 'chọn tối đa (id) ...'
'chọn @cus_id = max (id) + 1 từ khách hàng'
Tạ
Ollie
Sử dụng Projection:
session.CreateCriteria(typeof(Customer))
.SetProjection(Projections.Max("Id"))
. UniqueResult();
Max (id) + 1 là một cách rất xấu để tạo id. Nếu đó là mục tiêu của bạn, hãy tìm cách khác để tạo id.
Edit: trong câu trả lời cho LnDCobra:
nó xấu vì thật khó để chắc chắn rằng max (id), bạn có vẫn là max (id) khi bạn làm các việc chèn. Nếu một quá trình khác chèn một hàng, chèn của bạn sẽ có cùng một id và chèn của bạn sẽ thất bại. (Hoặc, ngược lại, quá trình chèn của quá trình khác sẽ thất bại nếu quá trình chèn của bạn đã xảy ra trước.)
Để ngăn chặn điều này, bạn hãy tránh và chèn nguyên tử khác, thường có nghĩa là khóa bảng sẽ làm tổn thương hiệu suất.
Nếu bạn chỉ khóa chống ghi, quy trình khác sẽ nhận được số tiền tối đa (id), cùng số tiền tối đa (id) bạn nhận được. Bạn làm chèn của bạn và phát hành khóa, nó chèn một id trùng lặp và không thành công. Hoặc nó cũng cố khóa lại, trong trường hợp nó chờ đợi bạn. Nếu bạn khóa chống lại lần đọc quá, mọi người chờ đợi bạn. Nếu nó khóa chống lại viết cũng, sau đó nó không chèn id trùng lặp, nhưng nó chờ đợi trên đọc của bạn và viết của bạn.
(Và nó phá vỡ đóng gói: bạn nên để cho các RDBMS tìm ra id của nó, không phải là các chương trình client kết nối với nó.)
Nói chung, chiến lược này sẽ hoặc là:
* phá vỡ
* yêu cầu bó "plumbing" mã làm việc
* giảm mạnh hiệu
* hoặc ba
và sẽ chậm, ít mạnh và cần hard giữ đang chỉ bằng của RDBMS built trong sequences hoặc tạo id autoincrement.
Ai đó có thể chỉ cho tôi đúng hướng là tại sao không sử dụng điều này để tạo id và nếu vậy thì tốt hơn ...? –
cách tiếp cận tốt nhất là làm cho bảng Trình tự bổ sung. Nơi bạn có thể duy trì mục tiêu và giá trị chuỗi.
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 - khi bạn cần duy trì các trình tự khác nhau cho cùng một thực thể, dựa trên một số loại chủ sở hữu. Ví dụ: bạn cần phải duy trì đánh số tài liệu trong hợp đồng, sau đó OwnerId will be = contractId
Loại trả về từ biểu thức này là gì? – IanT8
Một đối tượng. Bạn có thể sử dụng quá tải UniqueResult để truyền cho một loại cụ thể. Trong trường hợp này, bạn sẽ muốn UniqueResult () để truyền nó thành một số nguyên. –