首先,我是NHibernate的新手.我在许多页面中搜索了QueryOver的内容,但对我来说最有利可图的页面是http://nhibernate.info/blog/2009/12/17/queryover-in-nh-3-0.html.多亏了它,我想到了一个"半解决方案",但我需要这个解决方案更好.
我有这些课程:
public class Variable
{
public virtual int Id {get; set; }
public virtual string Nombre { get; set; }
public virtual string Descripcion { get; set; }
public virtual IList<ValorVariable> Valores { get; set; }
public virtual bool Temporal { get; set; }
public virtual bool Eliminado{ get; set; }
}
public class ValorVariable
{
public virtual int Id {get; set; }
public virtual int IdVariable { get; set; }
public virtual Variable Variable { get; set; }
public virtual DateTime FechaValor { get; set; }
public virtual decimal Valor { get; set; }
}
public class VariableLigera
{
public virtual int Id {get; set; }
public string Nombre { get; set; }
public string Descripcion { get; set; }
public bool Temporal { get; set; }
public Decimal Valor { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
变量是"重要"类,除其他外,它具有IList"ValorVariable",具有值("Valor")和值日期("FechaValor")."VariableLigera"就像一个"轻"类变量,具有Variable的一些属性和ValorVariable List的一个值.我希望这很清楚.
要填充VariableLigera,我正在尝试执行QueryOver.我想做这样的事情:
Variable variableAlias = null;
VariableLigera variableLigeraAlias = null;
var result = _session
.QueryOver(() => variableAlias ).Where(x => x.Eliminado == false)
.Select(
Projections.Property(() => variableAlias .Id).WithAlias(() => variableLigeraAlias .Id),
Projections.Property(() => variableAlias .Nombre).WithAlias(() => variableLigeraAlias .Nombre),
Projections.Property(() => variableAlias .Descripcion).WithAlias(() => variableLigeraAlias .Descripcion),
Projections.Property(() => variableAlias .Temporal).WithAlias(() => variableLigeraAlias .Temporal),
Projections.Property(() => variableAlias .Valores.FirstOrDefault().Valor).WithAlias(() => variableLigeraAlias .Valor)
)
.TransformUsing(Transformers.AliasToBean<VariableLigera>())
.List<VariableLigera>();
Run Code Online (Sandbox Code Playgroud)
这就是问题所在.我想将变量LigeraAlias的属性"Valor"放入变量列表的Valores列表的FirstOrDefault值.但它抛出一个异常,"函数FirstOrDefault无法识别".
所以我尝试了另一件事,为ValorVariable创建一个别名并将其加入查询.像这样:
Variable variableAlias = null;
VariableLigera variableLigeraAlias = null;
ValorVariable valorVariableAlias = null;
var result = _session
.QueryOver(() => variableAlias).Where(x => x.Eliminado == false)
.JoinAlias(() => variableAlias.Valores, () => valorVariableAlias)
.Select(
Projections.Property(() => variableAlias.Id).WithAlias(() => variableLigeraAlias.Id),
Projections.Property(() => variableAlias.Nombre).WithAlias(() => variableLigeraAlias.Nombre),
Projections.Property(() => variableAlias.Descripcion).WithAlias(() => variableLigeraAlias.Descripcion),
Projections.Property(() => variableAlias.Temporal).WithAlias(() => variableLigeraAlias.Temporal),
Projections.Property(() => valorVariableAlias.Valor).WithAlias(() => variableLigeraAlias.Valor)
)
.TransformUsing(Transformers.AliasToBean<VariableLigera>())
.List<VariableLigera>();
Run Code Online (Sandbox Code Playgroud)
通过这个查询,我得到了结果,但是我得到了每个变量很多次(ValoresVariables列表中每个值有一个重复).例如,如果一个变量有3个值,查询将返回带有3个值的3个"VariablesLigera",但我只想要一个带有它的列表的第一个值.
简而言之,为了清楚起见,我希望每个变量都有一个结果,其值为("Valor")列表中的firstordefault值.是否可以使用QueryOver?非常感谢.
PS:因为英语不是我的母语,也许有些事情不太容易理解.如果有任何疑问,请随时询问.再次感谢.
使用QueryOver查询时要记住的事情是它们最终变成了SQL.考虑到这一点,无论何时访问嵌套属性,都需要考虑连接或子查询来完成工作.
在这种情况下,您需要使用子查询来获取第一个ValorVariable.Valor:
Variable variableAlias = null;
VariableLigera variableLigeraAlias = null;
var result = _session
.QueryOver(() => variableAlias).Where(x => x.Eliminado == false)
.Select(
Projections.Property(() => variableAlias.Id).WithAlias(() => variableLigeraAlias.Id),
Projections.Property(() => variableAlias.Nombre).WithAlias(() => variableLigeraAlias.Nombre),
Projections.Property(() => variableAlias.Descripcion).WithAlias(() => variableLigeraAlias.Descripcion),
Projections.Property(() => variableAlias.Temporal).WithAlias(() => variableLigeraAlias.Temporal),
Projections.Subquery(
QueryOver.Of<ValorVariable>()
.Where(vv => vv.Variable.Id == variableAlias.Id)
.Select(vv => vv.Valor)
.Take(1)
).WithAlias(() => variableLigeraAlias.Valor)
)
.TransformUsing(Transformers.AliasToBean<VariableLigera>())
.List<VariableLigera>();
Run Code Online (Sandbox Code Playgroud)
这将生成如下所示的SQL:
SELECT
/*Variable properties */
(
SELECT
TOP(1) this_0_.Valor AS y0_
FROM
ValorVariable this_0_
WHERE
this_0_.VariableID = this_.ID
) AS y1_
FROM
Variable this_
WHERE
this_.Eliminado = 0
Run Code Online (Sandbox Code Playgroud)
现在,正如@Carl指出的那样,你可能应该通过某种方式来命令你的子查询结果,以便取"第一条记录"实际意味着什么.
为此,您可以OrderBy向子查询添加:
QueryOver.Of<ValorVariable>()
.Where(vv => vv.Variable.Id == variableAlias.Id)
.Select(vv => vv.Valor)
.OrderBy(vv => vv.FechaValor).Desc
.Take(1)
Run Code Online (Sandbox Code Playgroud)
哪个会产生类似的SQL,除了一个ORDER BY子句.
此外,由于您使用FirstOrDefault,这意味着该Valor财产可能存在null.如果是这种情况,您应该将您的VariableLigera.Valor属性更新为decimal?(可为空decimal).
| 归档时间: |
|
| 查看次数: |
924 次 |
| 最近记录: |