NHibernate扩展用于查询非映射属性

时间:2015-03-02 09:52:20

标签: c# nhibernate extension-methods projection queryover

我正在寻找一种从我的对象中的“成本”列表中获取总价格数的方法。我无法获得Projections.Sum在我的QueryOver中工作,所以我尝试了另一种方式,但我遇到了问题。我想在QueryOver中使用未映射的属性。我找到了这个例子,但它给出了一个错误。

对象

public class Participant
{
    public int Id { get; set; }
    public double TotalPersonalCosts { get { return Costs.Where(x => x.Code.Equals("Persoonlijk") && x.CostApprovalStatus == CostApprovalStatus.AdministratorApproved).Sum(x => x.Price.Amount); } }
    public IList<Cost> Costs { get; set; }
}

未映射属性TotalPersonalCosts并包含总价格计数。

扩展类:

public static class ParticipantExtensions
{
    private static string BuildPropertyName(string alias, string property)
    {
        if (!string.IsNullOrEmpty(alias))
        {
            return string.Format("{0}.{1}", alias, property);
        }

        return property;
    }

    public static IProjection ProcessTotalPersonalCosts(System.Linq.Expressions.Expression expr)
    {
        Expression<Func<Participant, double>> w = r => r.TotalPersonalCosts;

        string aliasName = ExpressionProcessor.FindMemberExpression(expr);
        string totalPersonalCostName = ExpressionProcessor.FindMemberExpression(w.Body);

        PropertyProjection totalPersonalCostProjection =
            Projections.Property(BuildPropertyName(aliasName, totalPersonalCostName));

        return totalPersonalCostProjection;
    }
}

我的QueryOver:

public override PagedList<AccountantViewInfo> Execute()
    {
       ExpressionProcessor.RegisterCustomProjection(
            () => default(Participant).TotalPersonalCosts,
            expr => ParticipantExtensions.ProcessTotalPersonalCosts(expr.Expression));

        AccountantViewInfo infoLine = null;
        Trip tr = null;
        Participant pa = null;
        Cost c = null;
        Price p = null;

        var infoLines = Session.QueryOver(() => tr)
            .JoinAlias(() => tr.Participants, () => pa);

        if (_status == 0)
            infoLines.Where(() => pa.TotalCostApprovalStatus == TotalCostApprovalStatus.CostPrinted || pa.TotalCostApprovalStatus == TotalCostApprovalStatus.CostPaid);
        else if (_status == 1)
            infoLines.Where(() => pa.TotalCostApprovalStatus == TotalCostApprovalStatus.CostPrinted);
        else
            infoLines.Where(() => pa.TotalCostApprovalStatus == TotalCostApprovalStatus.CostPaid);

        infoLines.WhereRestrictionOn(() => pa.Employee.Id).IsIn(_employeeIds)
                .Select(
                    Projections.Property("pa.Id").WithAlias(() => infoLine.Id),
                    Projections.Property("pa.Employee").WithAlias(() => infoLine.Employee),
                    Projections.Property("pa.ProjectCode").WithAlias(() => infoLine.ProjectCode),
                    Projections.Property("tr.Id").WithAlias(() => infoLine.TripId),
                    Projections.Property("tr.Destination").WithAlias(() => infoLine.Destination),
                    Projections.Property("tr.Period").WithAlias(() => infoLine.Period),
                    Projections.Property("pa.TotalPersonalCosts").WithAlias(() => infoLine.Period)
                );

        infoLines.TransformUsing(Transformers.AliasToBean<AccountantViewInfo>());

        var count = infoLines.List<AccountantViewInfo>().Count();
        var items = infoLines.List<AccountantViewInfo>().ToList().Skip((_myPage - 1) * _itemsPerPage).Take(_itemsPerPage).Distinct();

        return new PagedList<AccountantViewInfo>
        {
            Items = items.ToList(),
            Page = _myPage,
            ResultsPerPage = _itemsPerPage,
            TotalResults = count,
        };
    }

此处无法从expr。

中找到.Expression属性

我不知道自己做错了什么。任何帮助或替代品将不胜感激!

使用Projection.Sum()thx to xanatos

的解决方案
.Select(
                    Projections.Group(() => pa.Id).WithAlias(() => infoLine.Id),
                    Projections.Group(() => pa.Employee).WithAlias(() => infoLine.Employee),
                    Projections.Group(() => pa.ProjectCode).WithAlias(() => infoLine.ProjectCode),
                    Projections.Group(() => tr.Id).WithAlias(() => infoLine.TripId),
                    Projections.Group(() => tr.Destination).WithAlias(() => infoLine.Destination),
                    Projections.Group(() => tr.Period).WithAlias(() => infoLine.Period),
                    Projections.Sum(() => c.Price.Amount).WithAlias(() => infoLine.TotalPersonalCost)
                );

1 个答案:

答案 0 :(得分:0)

您不能将未映射的列用作NHibernate查询的投影列。

您尝试这样做的方式在概念上是错误的:ParticipantExtensions方法将在执行查询到服务器之前调用,其目的是修改将要执行的SQL查询。 IProjectionProcessTotalPersonaCosts返回的“事物”)将放在查询中的SELECT和FROM之间。 SQL服务器无法返回TotalCosts,因为SQL不知道TotalCosts