检查数据库中是否存在对象而不使用NHibernate加载对象

时间:2010-08-19 20:14:06

标签: nhibernate

在NHibernate中是否有办法检查数据库中是否存在对象而无需获取/加载对象?

9 个答案:

答案 0 :(得分:30)

您可以使用以下3个查询之一(或者您可以使用David回答的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 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

答案 1 :(得分:9)

可以随时计算。

我倾向于使用DetachedCriteria,所以我有类似的东西:

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

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

return result > 0;

答案 2 :(得分:9)

所以我让自己用你的例子@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;

是最好的选择,因为良好的习惯和代码清晰度

答案 3 :(得分:6)

要扩展Darius Kucinskas的优秀答案,您可以避免使用Select来获取实体:

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

如前所述,查询性能应该相同,但我希望这可以减少网络流量。

答案 4 :(得分:3)

我认为你正在寻找这个......

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

答案 5 :(得分:2)

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

答案 6 :(得分:0)

基于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;

答案 7 :(得分:0)

你可以尝试一下:

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

答案 8 :(得分:0)

我根据以上答案创建了扩展方法。我选择使用“任意”版本,但是在主键上选择了“选择”,根据主键类型,将返回相同数量的数据。

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);
}