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

Tob*_*san 22 nhibernate

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

Dar*_*kas 29

您可以使用以下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;
Run Code Online (Sandbox Code Playgroud)

请记住,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
Run Code Online (Sandbox Code Playgroud)

  • OTOH,从性能角度来看,任何一个都可能是最好的 - "count"可以是一个重要的函数来调用,具体取决于数据量,索引等.TOP(1)只会寻找合适的指数.是否有相当于`SELECT TOP(1)1 FROM table WHERE ...`这将是最好的(因为它实际上不会从表中提取任何数据). (11认同)

Dav*_*vid 9

可以随时做点算.

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

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

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

return result > 0;
Run Code Online (Sandbox Code Playgroud)


Seb*_*563 9

所以我让自己用你的例子做一些测试 @Jamie Ide @Darius Kucinskas @Dmitry

在此输入图像描述

所以:

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

在我的情况下比18%

bool exist = session.Query<Employee>()
    .Any(x => x.EmployeeID == 1);
Run Code Online (Sandbox Code Playgroud)

14%

bool exist = session.Query<Employee>()
    .Count(x => x.EmployeeID == 1) > 0;
Run Code Online (Sandbox Code Playgroud)

8%

bool exist = session.QueryOver<Employee>()
    .Where(x => x.EmployeeID == 1)
    .RowCount() > 0;
Run Code Online (Sandbox Code Playgroud)

所以在我看来,即使硬编码查询是最快的

bool exist = session.QueryOver<Employee>()
    .Where(x => x.EmployeeID == 1)
    .RowCount() > 0;
Run Code Online (Sandbox Code Playgroud)

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


Jam*_*Ide 6

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

bool exist = session.Query<Employee>()
                    .Where(x => x.EmployeeID == 1)
                    .Select(x => x.EmployeeID)
                    .Any();
Run Code Online (Sandbox Code Playgroud)

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