2013-08-08 10 views
6

Mit NHibernate Einheiten:Linq to NHibernate: Summe der Beträge

Company, Invoice und InvoiceLine die Price eine Dezimalzahl Eigenschaft hat.

Eine Company hat eine Sammlung von Typ Invoice, und eine Invoice hat eine Sammlung von Typ InvoiceLine.

Wie kann ich die Summe aller Preise erhalten, die zu Rechnungszeilen gehören, die zu Rechnungen einer bestimmten Firma gehören, die durch id spezifiziert sind?

Ich habe versucht, die Abfrage wie folgt zu schreiben:

session 
    .Query<InvoiceLine>() 
    .Where(invoiceLine => invoiceLine.Invoice.Company.Id == companyId) 
    .Sum(invoiceLine => invoiceLine.Price); 

aber es löst eine Ausnahme:

NHibernate.Exceptions.GenericADOException 
"Could not execute query[SQL: SQL not available]" 

    at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) 
    at NHibernate.Impl.AbstractSessionImpl.List(IQueryExpression queryExpression, QueryParameters parameters) 
    at NHibernate.Impl.ExpressionQueryImpl.List() 
    at NHibernate.Linq.DefaultQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery) 
    at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) 
    at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression) 
    at System.Linq.Queryable.Sum[TSource](IQueryable`1 source, Expression`1 selector) 

innere Ausnahme:

System.ArgumentNullException 
"Value cannot be null.\r\nParameter name: item" 

    at System.ThrowHelper.IfNullAndNullsAreIllegalThenThrow[T](Object value, ExceptionArgument argName) 
    at System.Collections.Generic.List`1.System.Collections.IList.Add(Object item) 
    at NHibernate.Util.ArrayHelper.<>c__DisplayClass2.<AddAll>b__0() 
    at NHibernate.Util.ArrayHelper.AddAll(IList to, IList from) 
    at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results) 
    at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) 

Dies könnte etwas mit dem zu tun haben summing leere Sammlungen, aber ich bin mir nicht sicher, wie man es repariert.

Antwort

7

Versuchen Sie, die Price Casting decimal auf NULL-Werte zulässt ...

.Sum(invoiceLine => (decimal?)invoiceLine.Price) ?? 0; 

Das Ergebnis eindeutig ein decimal?

+0

Dies ist fast die Lösung, bitte ändern Sie es in '.Summe (invoiceLine => (Dezimal?) RechnungLine.Price) ?? 0, also kann ich aufheben und akzeptieren. –

0
session 
    .Query<InvoiceLine>() 
    .Where(invoiceLine => invoiceLine.Invoice.Company.Id == companyId && invoiceLine.Price != null) 
    .Sum(invoiceLine => (decimal)invoiceLine.Price); 
0
ist

Die Lösung als Antwort markiert nicht das Problem für mich retten. Anstelle von GenericAdoException habe ich eine InvalidOperationException mit folgendem Stack erhalten.

Vorgeschlagene Lösung hier Linq: select property collection ist die eigentliche Lösung für mich.

Une erreur inattendue de type InvalidOperationException s'est produite sur le serveur 
System.InvalidOperationException: Code supposed to be unreachable 
    à System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack) 
    à System.Linq.Expressions.Compiler.StackSpiller.RewriteUnaryExpression(Expression expr, Stack stack) 
    à System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack) 
    à System.Linq.Expressions.Compiler.StackSpiller.RewriteExpressionFreeTemps(Expression expression, Stack stack) 
    à System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda) 
    à System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller) 
    à System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator) 
    à System.Linq.Expressions.Expression`1.Compile() 
    à NHibernate.Linq.ExpressionToHqlTranslationResults.MergeLambdasAndCompile[TDelegate](IList`1 itemTransformers) 
    à NHibernate.Linq.ExpressionToHqlTranslationResults..ctor(HqlTreeNode statement, IList`1 itemTransformers, IList`1 listTransformers, IList`1 postExecuteTransformers, List`1 additionalCriteria) 
    à NHibernate.Linq.IntermediateHqlTree.GetTranslation() 
    à NHibernate.Linq.Visitors.QueryModelVisitor.GenerateHqlQuery(QueryModel queryModel, VisitorParameters parameters, Boolean root) 
    à NHibernate.Linq.NhLinqExpression.Translate(ISessionFactoryImplementor sessionFactory, Boolean filter) 
    à NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory) 
    à NHibernate.Engine.Query.QueryExpressionPlan.CreateTranslators(IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory) 
    à NHibernate.Engine.Query.QueryExpressionPlan..ctor(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory) 
    à NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters) 
    à NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow) 
    à NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression) 
    à NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery) 
    à NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) 
    à NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression) 
    à System.Linq.Queryable.Sum[TSource](IQueryable`1 source, Expression`1 selector) 
    à Secib.Server.Services.ReglementService.GetRegleTtc(FactureView facture) dans x:\Sources\Next\Alpha\SecibNext\Secib.Server\Services\ReglementService.cs:ligne 425 
    à Secib.Server.Services.ReglementService.DoesMontantSoldeFacture(FactureView facture, Decimal montantImpute) dans x:\Sources\Next\Alpha\SecibNext\Secib.Server\Services\ReglementService.cs:ligne 391 
    à Secib.Server.Services.ReglementService.DispatcheMontantImpute(Reglement reglement, ReglementFactureCompactDto factureDto) dans x:\Sources\Next\Alpha\SecibNext\Secib.Server\Services\ReglementService.cs:ligne 236 
    à Secib.Server.Services.ReglementService.SaveReglement(Reglement reglement, IList`1 factures) dans x:\Sources\Next\Alpha\SecibNext\Secib.Server\Services\ReglementService.cs:ligne 197 
    à Secib.Server.Controllers.ReglementController.<SaveReglement>z__OriginalMethod() dans x:\Sources\Next\Alpha\SecibNext\Secib.Server\Controllers\ReglementController.cs:ligne 141 
    à Secib.Server.Controllers.ReglementController.<SaveReglement>c__Binding.Invoke(Object& instance, Arguments arguments, Object aspectArgs) dans :ligne 0 
    à PostSharp.Aspects.Internals.MethodInterceptionArgsImpl`1.Proceed() 
    à Secib.Server.Aspects.TransactionAspect.OnInvoke(MethodInterceptionArgs args) dans x:\Sources\Next\Alpha\SecibNext\Secib.Server\Aspects\TransactionAspect.cs:ligne 32 
+0

Welche innere Ausnahme bekommen Sie und wie sahen Ihre Abfragen/Entitäten aus? Wenn sich nicht etwas in der Art und Weise ändert, wie es funktioniert, bin ich mir ziemlich sicher, dass die akzeptierte Antwort funktioniert. –

+0

Das 'SelectMany' zweite Code-Stück macht auch 2 Anfragen an die DB statt 1 (könnte mit Futures geschrieben werden, aber es wäre immer noch weniger effizient). –

+0

InnerException ist null. Die Abfrage ist sehr einfach und sehr ähnlich wie bei Ihnen: return Session.Query () \t \t \t \t .Where (x => x.Facture == Faktur) \t \t \t \t .sum (x => (dezimal?) x.MontantRegle ?? 0); Wobei Facture von ReglementFacture referenziert wird (viele zu eins) und MontantRegle ist dezimal (und die Spalte ist nicht nullfähig). NH v 4.0.0.4000 –