[英]NHibernate: How to return list of scalar values (from one column) using CreateSQLQuery?
What is the best/cleanest method of calling a native SQL returning a list of scalar values (ints in my case) having ISession object? 调用本机SQL返回具有ISession对象的标量值(本例中为int)列表的最佳/最干净方法是什么?
I am trying to run the following but I am always getting some errors: 我正在尝试运行以下命令,但始终会遇到一些错误:
var query = _session.CreateSQLQuery("SELECT Id FROM SomeTable");
A. var ids = query.List<int>(); // <-- throws ArgumentNullException "Value cannot be null.\r\nParameter 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'"
Is there a way to retrieve a list of ints without creating an entity class containing just one int property named Id? 有没有一种方法可以检索整数列表,而无需创建仅包含一个名为Id的整数属性的实体类?
When you call List
from CreateSQLQuery
you will get a instance of IList
and it internally it is a List<object>
. 当您从
CreateSQLQuery
调用List
,将获得IList
一个实例,它在内部是List<object>
。 If you have null values on this result, you will not be able to convert to int
because it is a value type. 如果此结果具有空值,则将无法转换为
int
因为它是值类型。 So, a solution is to iterate over the result and convert it when it is a valid integer. 因此,一种解决方案是迭代结果,并在结果为有效整数时对其进行转换。 For sample:
样品:
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));
}
If this is a mapped table on the nhibernate scope, you could use LINQ to do this, for sample: 如果这是nhibernate范围内的映射表,则可以使用LINQ进行此操作,例如:
var ids = session.Query<SomeEntity>().Select(x => x.Id).ToList();
I know you are not using IQueryOver
, but it is simpler, dynamic and cleaner than the way you are doing this now. 我知道您没有使用
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
in above code is entity that represent (mapped to) your table. 上面代码中的
TEntity
是表示(映射到)表的实体。 Note that this is just to build the query. 请注意,这只是建立查询。 It will NOT return Entity.
它不会返回实体。
TReturn
is the return type. TReturn
是返回类型。 This can be any standard data type like int
in your case. 这可以是任何标准数据类型,例如
int
。
IProjection column
parameter is the name of the column you want to select. IProjection column
参数是您要选择的列的名称。
Junction where
parameter allows you to specify the filter on rows if any. Junction where
参数允许您在行上指定过滤器(如果有)。 To retrieve all rows, pass it null
. 要检索所有行,请将其传递为
null
。
Following is the way you call it: 以下是您的称呼方式:
Junction where = Restrictions.Conjunction();
where.Add(Restrictions.Eq(..........));
IList<int> idList = GetValues<SomeTableEntity, int>(Projections.Property<SomeTableEntity>(x => x.Id), where, 0);
This way, you avoid writing hard-coded SQL query as string in your code. 这样,您可以避免在代码中将硬编码的SQL查询作为字符串编写。 As you can see, this function can be used with any Entity (table) and any column.
如您所见,此函数可以与任何实体(表)和任何列一起使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.