在NHibernate中是否有办法检查数据库中是否存在对象而无需获取/加载对象?
答案 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
所以:
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);
}