gpt4 book ai didi

nhibernate - NHibernate嵌套投影

转载 作者:行者123 更新时间:2023-12-02 04:04:09 24 4
gpt4 key购买 nike

甚至不确定是否有可能,但我还是会解释。

我有一个用于在查询中执行简单算术的自定义投影,该查询可以在单个投影中完美运行。

namespace Custom.Projections
{
using System.Collections.Generic;
using System.Text;
using global::NHibernate;
using global::NHibernate.Criterion;
using global::NHibernate.SqlCommand;
using global::NHibernate.Type;

/// <summary>
/// Represents a CalculatedProjection
/// </summary>
public class CalculatedProjection : SimpleProjection
{
private readonly CalculationType calculationType;
private readonly IProjection firstProjection;
private readonly IProjection secondProjection;
private readonly string firstPropertyName;
private readonly string secondPropertyName;

/// <summary>
/// Initializes a new instance of the CalculatedProjection class
/// </summary>
/// <param name="type">The type of calculation</param>
/// <param name="firstPropertyName">The name of the first property</param>
/// <param name="secondPropertyName">The name of the second property</param>
protected internal CalculatedProjection(CalculationType type, string firstPropertyName, string secondPropertyName)
{
this.calculationType = type;
this.firstPropertyName = firstPropertyName;
this.secondPropertyName = secondPropertyName;
System.Diagnostics.Debugger.Launch();
}

/// <summary>
/// Initializes a new instance of the CalculatedProjection class
/// </summary>
/// <param name="type">The type of calculation</param>
/// <param name="firstProjection">The first projection</param>
/// <param name="secondProjection">The second projection</param>
protected internal CalculatedProjection(CalculationType type, IProjection firstProjection, IProjection secondProjection)
{
this.calculationType = type;
this.firstProjection = firstProjection;
this.secondProjection = secondProjection;
}

/// <summary>
/// The type of calculation
/// </summary>
public enum CalculationType
{
/// <summary>
/// Addition +
/// </summary>
Addition,

/// <summary>
/// Subtraction -
/// </summary>
Subtraction,

/// <summary>
/// Division /
/// </summary>
Division,

/// <summary>
/// Division *
/// </summary>
Multiplication,
}

/// <summary>
/// Gets a value indicating whether the projection is grouped
/// </summary>
public override bool IsGrouped
{
get { return false; }
}

/// <summary>
/// Gets a value indicating whether IsAggregate.
/// </summary>
public override bool IsAggregate
{
get { return false; }
}

/// <summary>
/// Converts the calculation into a string
/// </summary>
/// <returns>The string representation of the calculation</returns>
public override string ToString()
{
var firstValue = this.firstProjection != null ? this.firstProjection.ToString() : this.firstPropertyName;
var secondValue = this.secondProjection != null ? this.secondProjection.ToString() : this.secondPropertyName;

return "(" + firstValue + TypeToString(this.calculationType) + secondValue + ")";
}

/// <summary>
/// Gets the types involved in the query
/// </summary>
/// <param name="criteria">The current criteria</param>
/// <param name="criteriaQuery">The criteria query</param>
/// <returns>An array of IType</returns>
public override IType[] GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
var types = new List<IType>();

if (this.firstProjection != null)
{
types.AddRange(this.firstProjection.GetTypes(criteria, criteriaQuery));
}
else
{
types.Add(criteriaQuery.GetType(criteria, this.firstPropertyName));
}

if (this.secondProjection != null)
{
types.AddRange(this.secondProjection.GetTypes(criteria, criteriaQuery));
}
else
{
types.Add(criteriaQuery.GetType(criteria, this.secondPropertyName));
}

return types.ToArray();
}

/// <summary>
/// Converts the objects to an sql string representation
/// </summary>
/// <param name="criteria">The criteria being used in the query</param>
/// <param name="loc">The location in the query</param>
/// <param name="criteriaQuery">The criteria query</param>
/// <param name="enabledFilters">List of enabled filters</param>
/// <returns>The calculation as an sql string</returns>
public override SqlString ToSqlString(ICriteria criteria, int loc, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
{
string first, second;

if ((this.firstProjection != null) && (this.secondProjection != null))
{
first = global::NHibernate.Util.StringHelper.RemoveAsAliasesFromSql(this.firstProjection.ToSqlString(criteria, loc, criteriaQuery, enabledFilters)).ToString();
second = global::NHibernate.Util.StringHelper.RemoveAsAliasesFromSql(this.secondProjection.ToSqlString(criteria, loc, criteriaQuery, enabledFilters)).ToString();
}
else
{
first = criteriaQuery.GetColumn(criteria, this.firstPropertyName);
second = criteriaQuery.GetColumn(criteria, this.secondPropertyName);
}

return new SqlString(new object[] { "(", first, TypeToString(this.calculationType), second, ") as y", loc.ToString(), "_" });
}

/// <summary>
/// Converts the objects to an sql string representation
/// </summary>
/// <param name="criteria">The criteria being used in the query</param>
/// <param name="criteriaQuery">The criteria query</param>
/// <param name="enabledFilters">List of enabled filters</param>
/// <returns>The calculation as an sql string</returns>
public override SqlString ToGroupSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters)
{
var sb = new StringBuilder();

return new SqlString(new object[] { sb.ToString() });
}

/// <summary>
/// Returns the string symbol of calculation type
/// </summary>
/// <param name="type">The type to use</param>
/// <returns>The string representation</returns>
private static string TypeToString(CalculationType type)
{
switch (type)
{
case CalculationType.Addition: return "+";
case CalculationType.Subtraction: return "-";
case CalculationType.Multiplication: return "*";
case CalculationType.Division: return "/";
default: return "+";
}
}
}
}

我现在尝试使用QueryOver语法从另一个内部使用此投影,如下所示:
public override IList<DaySummaryDetail> Execute()
{
// ReSharper disable PossibleNullReferenceException
var calculated = Custom.Projections.Calculated(CalculatedProjection.CalculationType.Subtraction, "Duration.EndTime", "Duration.StartTime");

DaySummaryDetail detail = null;

return Session.QueryOver<WorkingDay>()
.SelectList(list => list
.Select(Projections.Group<WorkingDay>(x => x.Date).WithAlias(() => detail.Date))
.Select(Projections.Sum(calculated)).WithAlias(() => detail.TotalMinutes))
.Where(x => x.Person.Id == 1)
.TransformUsing(Transformers.AliasToBean<DaySummaryDetail>())
.List<DaySummaryDetail>();

// ReSharper restore PossibleNullReferenceException
}

生成的查询是正确的:
SELECT
this_.DATE_TIME as y0_,
sum((this_.END_MINS-this_.START_MINS)) as y1_
FROM
WORKINGDAY this_
WHERE
this_.PERSON_ID = @p0
GROUP BY
this_.DATE_TIME;
@p0 = 1 [Type: Int64 (0)]

我遇到的问题是出现以下异常:

NHibernate.Exceptions.GenericADOException:无法执行查询
[从工作日this_ WHEREDAY this_ WHERE this_.PERSON_ID = @ p0 GROUP BY this_.DATE_TIME选择y0_作为this_.DATE_TIME,sum((this_.END_MINS-this_.START_MINS))作为y1
名称:cp0-值:8977
[SQL:SELECT this_.DATE_TIME作为y0_,sum((this_.END_MINS-this_.START_MINS))作为y1_ FROM WORKINGDAY this_ WHERE this_.PERSON_ID = @ p0 GROUP BY this_.DATE_TIME]
----> System.IndexOutOfRangeException:y2_

堆栈跟踪:
at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name)
at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name)
at NHibernate.Loader.Criteria.CriteriaLoader.GetResultColumnOrRow(Object[] row, IResultTransformer customResultTransformer, IDataReader rs, ISessionImplementor session)
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
at NHibernate.Loader.Criteria.CriteriaLoader.List(ISessionImplementor session)
at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results)
at NHibernate.Impl.CriteriaImpl.List(IList results)
at NHibernate.Impl.CriteriaImpl.List()

从查询中可以看到,别名使用两个值(y0_和y1_),但以某种方式正在寻找y2_。
我认为这是因为我在此处使用了无法处理的嵌套投影,或者是我实现或错误地调用了投影?

任何帮助或替代建议将是巨大的。我意识到可以使用HQL等多种方式完成此操作,但对使用QueryOver尤其感兴趣

提前致谢

最佳答案

男生错误。

投影上的GetTypes方法应返回投影结果中涉及的类型。我正在返回涉及的字段类型。

应该看起来像这样:

public override IType[] GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
return new IType[] { NHibernateUtil.Int32 };
}

希望这可以节省一些时间

关于nhibernate - NHibernate嵌套投影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8563309/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com