Расширение NHibernate для запроса не сопоставленного свойства

Я ищу способ получить общее количество цен из списка затрат в моем объекте. Я не могу заставить Projection.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;
    }
}

Мой запрос:

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,
        };
    }

Здесь свойство.Expression не найдено из выражения expr.

Я не знаю, что я делаю не так. Любая помощь или альтернативы будут высоко ценится!

Решение с помощью 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 ответ

Вы не можете использовать несопоставленные столбцы в качестве столбцов проекции запроса NHibernate.

И то, как вы пытаетесь это сделать, концептуально неправильно: ParticipantExtensions методы будут вызываться ДО выполнения запроса к серверу, и их цель - изменить SQL-запрос, который будет выполнен. IProjection ("вещь", которая возвращается ProcessTotalPersonaCosts) - это то, что будет помещено между SELECT и FROM в запросе. TotalCosts не может быть возвращен сервером SQL, потому что SQL не знает о TotalCosts

Другие вопросы по тегам