2010-08-19 9 views

回答

9

總是可以做一個計數。

我傾向於使用DetachedCriteria之後,所以我有這樣的:

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

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

return result > 0; 
3

我認爲你正在尋找這...

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

這應該是var fooExists = session.Query ().Any(f =>/* condition * /)哪裏是多餘的。這是個壞主意,因爲Any會返回所有列(完整實體)。 – 2012-05-16 06:58:13

+0

@DariusKucinskas,這是不正確的。這兩個構造都導致了EXACT SAME SQL。使用'Any(x)'而不是'Where(x).Any()'只是更簡潔一些。 – 2012-06-27 15:59:24

+0

任何一個都不好,因爲它提取實體表單數據庫,在這種情況下行數更好。 – 2012-06-28 06:23:05

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

您可以使用以下3個查詢之一(或者你可以從使用標準API Projections.RowCountInt64()大衛回答):

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; 

請記住,任何是這三個中最糟糕的,因爲它提取實體。下面是每個生成的SQL查詢:

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,從性能的角度來看,任何一個都可能是最好的 - 根據數據量,索引等,「count」可能是一個繁重的函數。 TOP(1)只會尋求適當的索引。是否有相當於'SELECT TOP(1)1 FROM table WHERE ...'這將再次最好(因爲它實際上不會從表中抽取任何數據)。 – 2012-08-23 11:31:02

+1

+1查看詳細分類。 – JasonCoder 2013-07-18 17:01:32

+0

查看我的答案,查詢不會獲取實體或使用計數。 http://stackoverflow.com/a/24083783/12752 – 2014-06-06 14:07:35

5

要擴大大流士Kucinskas'優秀的答案,你能避免使用選擇獲取實體:

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

如前所述,查詢性能應該是相同的但我希望這可以減少網絡流量。

0

根據Ricardo答案,這似乎是使用HQL檢查對象是否存在的最有效方法。它不計算,並不一定會加載對象:

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

它生成此SQL(注意,這是SQLite的,所以限制,而不是TOP)

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

你可以試試:

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

所以我讓自己做一些測試與你的例子@Jamie Ide @Darius Kucinskas @Dmitry

enter image description here

所以:

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

18%快於

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

14%

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

8%

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

所以,在我看來,即使硬編碼的查詢是最快的

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

是最好的選擇,因爲良好的生活習慣和代碼清晰

相關問題