2010-08-19 36 views
19

Có cách nào trong NHibernate để kiểm tra xem một đối tượng tồn tại trong cơ sở dữ liệu mà không cần phải tải/tải đối tượng không?Kiểm tra xem đối tượng tồn tại trong cơ sở dữ liệu mà không tải đối tượng với NHibernate

+0

Tôi không hiểu. Nếu không có đối tượng nào trong DB, cách nhận hoặc tải một đối tượng. Đối tượng sẽ trở lại là null. Hoặc danh sách kết quả của bạn sẽ trống. –

Trả lời

9

luôn có thể làm một số.

tôi có xu hướng sử dụng DetachedCriteria, vì vậy tôi muốn có một cái gì đó như:

var criteria = // some criteria that will identify your object 

var result = criteria 
    .GetExecutableCriteria(Session) 
    .SetProjection(Projections.RowCountInt64()) 
    .UniqueResult(); 

return result > 0; 
3

Tôi nghĩ rằng bạn đang tìm kiếm này ...

var fooExists = session.Query<Foo>().Any(f => /*condition*/); 
+0

Điều này phải là var fooExists = session.Query () .Bất cứ điều kiện nào (f =>/* * /) ở đâu là dư thừa. Đây là ý tưởng tồi bởi vì Bất kỳ sẽ trả về tất cả các cột (thực thể đầy đủ). –

+0

@DariusKucinskas không chính xác. Cả hai cấu trúc đều dẫn đến SQL chính xác. Sử dụng 'Any (x)' thay vì 'Where (x) .Any()' chỉ là một chút sạch hơn. –

+0

Mọi thứ đều xấu vì nó tìm nạp cơ sở dữ liệu biểu mẫu thực thể, số lượng hàng tốt hơn trong tình huống này. –

2
var exists = 1 == session.CreateQuery("select 1 from MyEntity where Property = :value") 
    .SetValue("value", xxx) 
    .UniqueResult<Int32?>(); 
28

Bạn có thể sử dụng một trong 3 truy vấn sau đây (hoặc bạn có thể sử dụng Tiêu chuẩn API Projections.RowCountInt64() từ David trả lời):

bool exist = session.Query<Employee>() 
    .Any(x => x.EmployeeID == 1); 

bool exist = session.QueryOver<Employee>() 
    .Where(x => x.EmployeeID == 1) 
    .RowCount() > 0; 

bool exist = session.Query<Employee>() 
    .Count(x => x.EmployeeID == 1) > 0; 

Chỉ cần nhớ rằng bất kỳ điều gì là tồi tệ nhất trong ba trường hợp này vì nó tìm nạp thực thể. Dưới đây là truy vấn sql tạo ra cho mỗi:

exec sp_executesql N'select TOP (1) employee0_.EmployeeID as EmployeeID0_, employee0_.Name as Name0_ from Employee employee0_ where [email protected]',N'@p0 int',@p0=1 

exec sp_executesql N'SELECT count(*) as y0_ FROM Employee this_ WHERE this_.EmployeeID = @p0',N'@p0 int',@p0=1 

exec sp_executesql N'select cast(count(*) as INT) as col_0_0_ from Employee employee0_ where [email protected]',N'@p0 int',@p0=1 
+9

OTOH, Mọi thứ có thể là tốt nhất từ ​​góc độ hiệu suất - "đếm" có thể là một chức năng nhiệm vụ nặng để gọi, tùy thuộc vào khối lượng dữ liệu, chỉ mục và các tùy chọn tương tự. TOP (1) sẽ chỉ tìm kiếm chỉ số phù hợp. Có tương đương với 'SELECT TOP (1) 1 FROM table WHERE ...' mà sẽ là tốt nhất một lần nữa (vì nó sẽ không thực sự kéo bất kỳ dữ liệu nào từ bảng). –

+1

+1 để biết chi tiết về sự cố. – JasonCoder

+0

Xem câu trả lời của tôi cho một truy vấn không tìm nạp thực thể hoặc số lượng sử dụng. http://stackoverflow.com/a/24083783/12752 –

5

Để mở rộng về câu trả lời tuyệt vời Darius Kucinskas', bạn có thể tránh lấy đơn vị sử dụng Chọn:

bool exist = session.Query<Employee>() 
        .Where(x => x.EmployeeID == 1) 
        .Select(x => x.EmployeeID) 
        .Any(); 

Như đã đề cập, việc thực hiện truy vấn nên giống nhau tuy nhiên tôi hy vọng điều này sẽ giảm lưu lượng mạng.

0

Dựa trên câu trả lời Ricardo, đây có vẻ là cách hiệu quả nhất để kiểm tra xem đối tượng có tồn tại bằng HQL hay không.Nó không đếm và không nạp các đối tượng không cần thiết:

var exists = session 
    .CreateQuery("select 1 from Widget where _color = 'green'") 
    .SetMaxResults(1) 
    .UniqueResult<Int32?>() 
    .HasValue; 

nó tạo ra SQL này (lưu ý rằng đây là SQLite, do đó hạn chế thay vì TOP)

select 
    1 as col_0_0_ 
from 
    Widgets 
where 
    Color='green' limit 1; 
0

Bạn có thể có một thử :

public virtual T FindById<T>(int id) 
{ 
    return session.Get(typeof(T), id)); 
} 
8

Vì vậy, tôi để cho bản thân mình để làm một số xét nghiệm với các ví dụ của bạn @Jamie Ide @Darius Kucinskas @Dmitry

enter image description here

Vì vậy:

var exists = session 
.CreateQuery("select 1 from Widget where _color = 'green'") 
.SetMaxResults(1) 
.UniqueResult<Int32?>() 
.HasValue; 

trong trường hợp của tôi là 18% nhanh hơn

bool exist = session.Query<Employee>() 
    .Any(x => x.EmployeeID == 1); 

14% hơn

bool exist = session.Query<Employee>() 
    .Count(x => x.EmployeeID == 1) > 0; 

8%

bool exist = session.QueryOver<Employee>() 
    .Where(x => x.EmployeeID == 1) 
    .RowCount() > 0; 

Vì vậy, theo ý kiến ​​của tôi ngay cả khi truy vấn cứng mã hoá là nhanh nhất

bool exist = session.QueryOver<Employee>() 
    .Where(x => x.EmployeeID == 1) 
    .RowCount() > 0; 

là lựa chọn tốt nhất vì thói quen tốt và mã rõ nét

Các vấn đề liên quan