Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

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

return result > 0;

Ответ 2

Вы можете использовать один из следующих 3 запросов (или вы можете использовать Criteria 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;

Просто имейте в виду, что Any - это худший из этих трех, потому что он извлекает сущность. Здесь создается 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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

На основе Ricardo ответ кажется самым эффективным способом проверить, существует ли объект с использованием HQL. Он не выполняет COUNT и не загружает объект без необходимости:

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;

Ответ 8

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

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

Ответ 9

Я создал метод расширения из ответов выше. Я предпочитаю использовать любую версию, но при выборе Select для первичного ключа будет возвращаться один и тот же объем данных в зависимости от типа первичного ключа.

public static bool Exists<TModel, TKey>(
    this IQueryable<TModel> query, Expression<Func<TModel, TKey>> selector, TKey id)
    where TKey : class
{
    return query
        .Select(selector)
        .Any(x => x == id);
}

public static Task<bool> ExistsAsync<TModel, TKey>(
    this IQueryable<TModel> query, Expression<Func<TModel, TKey>> selector, TKey id)
    where TKey : class
{
    return query
        .Select(selector)
        .AnyAsync(x => x == id);
}