Проверьте, существует ли объект в базе данных без загрузки объекта с помощью NHibernate - PullRequest
22 голосов
/ 20 августа 2010

Есть ли способ в NHibernate проверить, существует ли объект в базе данных без необходимости получать / загружать объект?

Ответы [ 8 ]

30 голосов
/ 28 июня 2012

Вы можете использовать один из следующих 3 запросов (или вы можете использовать Criteria API Projection.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 employee0_.EmployeeID=@p0',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 employee0_.EmployeeID=@p0',N'@p0 int',@p0=1
9 голосов
/ 08 ноября 2015

Итак, я позволю себе провести несколько тестов с вашими примерами @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;

- лучший вариант из-за хороших привычек и четкости кода

9 голосов
/ 24 августа 2010

Может всегда делать подсчет.

Я склонен использовать DetachedCriteria, поэтому у меня будет что-то вроде:

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

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

return result > 0;
6 голосов
/ 06 июня 2014

Чтобы расширить превосходный ответ Дариуса Кучинскаса, вы можете избежать выборки сущности с помощью Select:

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

Как уже упоминалось, производительность запросов должна быть такой же, однако я ожидаю, что это уменьшит сетевой трафик.

3 голосов
/ 20 августа 2010

Я думаю, вы ищете это ...

var fooExists = session.Query<Foo>().Any(f => /*condition*/);
2 голосов
/ 27 июня 2012
var exists = 1 == session.CreateQuery("select 1 from MyEntity where Property = :value")
    .SetValue("value", xxx)
    .UniqueResult<Int32?>();
0 голосов
/ 29 июля 2015

Вы можете попробовать:

public virtual T FindById<T>(int id)
{
    return session.Get(typeof(T), id));
}
0 голосов
/ 04 июня 2015

Исходя из ответа Рикардо , это кажется наиболее эффективным способом проверки существования объекта с использованием HQL.Он не СЧИТАЕТ и не загружает объект без необходимости:

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

Он генерирует этот SQL (обратите внимание, что это SQLite, поэтому LIMIT вместо TOP)

select
    1 as col_0_0_ 
from
    Widgets  
where
    Color='green' limit 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...