NHibernate:如何使用CreateSQLQuery返回标量值列表(来自一列)



调用返回具有ISession对象的标量值(在我的例子中是int(列表的本机SQL的最佳/最干净的方法是什么?

我正在尝试运行以下程序,但我总是遇到一些错误:

var query = _session.CreateSQLQuery("SELECT Id FROM SomeTable");
A. var ids = query.List<int>(); // <-- throws ArgumentNullException "Value cannot be null.rnParameter name: item"
B. var ids = query.List(); returns one element array with no valid information.
C. query.SetResultTransformer(NHibernate.Transform.Transformers.AliasToBean<int>());
var ids = query.List<int>(); // throws PropertyNotFoundException: "Could not find a setter for property 'Id' in class 'System.Int32'"

有没有一种方法可以在不创建只包含一个名为Id的int属性的实体类的情况下检索int列表?

当您从CreateSQLQuery调用List时,您将获得IList的一个实例,它在内部是一个List<object>。如果此结果中有null值,则将无法转换为int,因为它是一种值类型。因此,解决方案是对结果进行迭代,并在结果为有效整数时进行转换。样品:

var values = _session.CreateSQLQuery("SELECT Id FROM SomeTable").List();
var ids = new List<int>();
foreach (var item in values)
{
if (item != null)
ids.Add(Convert.ToInt32(item));
}

如果这是nhibernate作用域上的映射表,您可以使用LINQ来执行此操作,例如:

var ids = session.Query<SomeEntity>().Select(x => x.Id).ToList();

我知道您没有使用IQueryOver,但它比您现在使用的方式更简单、更动态、更干净。

public IList<TReturn> GetValues<TEntity, TReturn>(IProjection column, Junction where, int top) where TEntity : BaseEntity
{
IQueryOver<TEntity> query = null;
if(where == null)
query = session.QueryOver<TEntity>().Select(column);
else
query = session.QueryOver<TEntity>().Select(column).Where(where);
IList<TReturn> instance = null;
if(top == 0)
instance = query.List<TReturn>();
else
instance = query.Take(top).List<TReturn>();
return instance;
}

上面代码中的TEntity是表示(映射到(您的表的实体。请注意,这只是为了构建查询。它不会返回实体。

TReturn是返回类型。在您的情况下,这可以是任何标准的数据类型,如int

IProjection column参数是要选择的列的名称。

Junction where参数允许您指定行上的筛选器(如果有的话(。要检索所有行,请将其传递给null

以下是您对它的称呼:

Junction where = Restrictions.Conjunction();
where.Add(Restrictions.Eq(..........));
IList<int> idList = GetValues<SomeTableEntity, int>(Projections.Property<SomeTableEntity>(x => x.Id), where, 0);

这样,您就可以避免在代码中将硬编码的SQL查询写成字符串。正如您所看到的,此函数可以用于任何实体(表(和任何列。

最新更新