Linq to Entities does not translate Math.Exp

I am trying to run a Linq to Entities query using Silverlight and RIA against a SQL Server database and I receive the following error :

LINQ to Entities does not recognize the method 'Double Exp(Double)' method, and this method cannot be translated into a store expression.

The lines causing the trouble are

            CalcChangeAmount = G.Sum(g => (double)g.PP.Quantity * (double)g.P0.Close * (double)(Math.Exp((double)(g.P1.PriceCummLogChange - g.P0.PriceCummLogChange)) - 1)),
            CalcAlphaAmount = G.Sum(g => (double)g.PP.Quantity * (double)g.P0.Close * (double)(Math.Exp((double)(g.P1.ActualCummLogAlpha - g.P0.ActualCummLogAlpha)) - 1))

in the attavched query.

Does anyone know why this is happening, and is there any sort of work-around?  Because of the size of the tables (and they are filtered on the silverlight side) it is not realistic to use ToList(0 or anything like that.

 
var PerformanceAnalysisIntermediate =
          from PP in ObjectContext.PortfolioPositions
          from TD in ObjectContext.DailyDates
          from FD in ObjectContext.DailyDates
          where PP.StartDate < TD.Date
          && (PP.EndDate >= FD.Date || PP.EndPrice == null)
          let StartDate = PP.StartDate < FD.Date ? FD.Date : PP.StartDate
          let EndDate = PP.EndDate > TD.Date || PP.EndDate == null ? TD.Date : PP.EndDate
          join P0 in ObjectContext.Prices
          on new { Date = ObjectContext.Prices.Where(p => p.EntityId == PP.EntityId && p.Close != null && p.ActualCummLogAlpha != null && p.Date <= StartDate).Max(p => p.Date), PP.EntityId } equals new { P0.Date, P0.EntityId }
          join P1 in ObjectContext.Prices
          on new { Date = ObjectContext.Prices.Where(p => p.EntityId == PP.EntityId && p.Close != null && p.ActualCummLogAlpha != null && p.Date <= EndDate).Max(p => p.Date), PP.EntityId } equals new { P1.Date, P1.EntityId }
          group new { PP, P0, P1, ToDate = TD.Date, FromDate = FD.Date } by new { PP.AccountEntityId, ToDate = TD.Date, FromDate = FD.Date, PP.EntityId } into G
          where G.Sum(g => g.P1.TCount - g.P0.TCount) > 0
          select new {
            G.Key.EntityId,
            G.Key.AccountEntityId,
            G.Key.FromDate,
            G.Key.ToDate,
            PCount = G.Count(),
            TCount = G.Max(g => g.P1.TCount) - G.Min(g => g.P0.TCount),
            StartDate = G.Min(g => g.PP.StartDate > g.FromDate ? g.PP.StartDate : g.P0.Date),
            EndDate = G.Max(g => g.PP.EndDate <= g.ToDate && g.PP.EndPrice != null ? g.PP.EndDate : g.P1.Date),
            AvgStartAmount = G.Sum(g => (double)g.PP.Quantity * (double?)(g.PP.StartDate > g.FromDate ? g.PP.StartPrice : g.P0.Close) * (double)(g.P1.TCount - g.P0.TCount)) / (double)G.Sum(g => g.P1.TCount - g.P0.TCount),
            AvgEndAmount = G.Sum(g => (double)g.PP.Quantity * (double?)(g.PP.EndDate <= g.ToDate && g.PP.EndPrice != null ? g.PP.EndPrice : g.P1.Close) * (double)(g.P1.TCount - g.P0.TCount)) / (double)G.Sum(g => g.P1.TCount - g.P0.TCount),
            AvgQuantity = G.Sum(g => (double)g.PP.Quantity * (double)(g.P1.TCount - g.P0.TCount)) / (double)G.Sum(g => g.P1.TCount - g.P0.TCount),
            AvgChangeAmount = G.Sum(g => (double)g.PP.Quantity * (double?)(g.PP.EndDate <= g.ToDate && g.PP.EndPrice != null ? g.PP.EndPrice : g.P1.Close) * (double)(g.P1.TCount - g.P0.TCount)) / (double)G.Sum(g => g.P1.TCount - g.P0.TCount)
                      - G.Sum(g => (double)g.PP.Quantity * (double?)(g.PP.StartDate > g.FromDate ? g.PP.StartPrice : g.P0.Close) * (double)(g.P1.TCount - g.P0.TCount)) / (double)G.Sum(g => g.P1.TCount - g.P0.TCount),
            CalcChangeAmount = G.Sum(g => (double)g.PP.Quantity * (double)g.P0.Close * (double)(Math.Exp((double)(g.P1.PriceCummLogChange - g.P0.PriceCummLogChange)) - 1)),
            CalcAlphaAmount = G.Sum(g => (double)g.PP.Quantity * (double)g.P0.Close * (double)(Math.Exp((double)(g.P1.ActualCummLogAlpha - g.P0.ActualCummLogAlpha)) - 1))
          };

Open in new window

eb8931Asked:
Who is Participating?
 
Craig WagnerConnect With a Mentor Software ArchitectCommented:
LINQ-to-Entities must be able to translate everything contained in the query into something that will execute on the server (i.e. database) side. It can't translate Math.Exp to something that will execute within the database query so you get that exception. This article talks about which framework methods can be converted to server-side methods.

http://msdn.microsoft.com/en-us/library/bb738681.aspx

Under many circumstances you can just do the calculation outside the query and use the results. Unfortunately in your case the value you're performing the calculation on is part of the query.

Math.Exp raises e to the specified power. Math also has a static member called E. Also, given the link provided above, the Pow method is supported by LINQ-to-Entities. So, if you did something like the following it should work.


CalcChangeAmount = G.Sum(g => (double)g.PP.Quantity * (double)g.P0.Close * (double)(Math.Pow(Math.E, (double)(g.P1.PriceCummLogChange - g.P0.PriceCummLogChange)) - 1)),

Open in new window

0
 
Fernando SotoConnect With a Mentor RetiredCommented:
Hi eb8931;

The Entity Framework has implemented many math functions which will translate to TSQL statements. These functions can be found at, SqlFunctions Class. To modify your statements to work add the using statement and change the word Math to SqlFunctions as shown in the code snippet below.

using System.Data.Objects.SqlClient;

CalcChangeAmount = G.Sum(g => (double)g.PP.Quantity * (double)g.P0.Close * (double)(SqlFunctions.Exp((double)(g.P1.PriceCummLogChange - g.P0.PriceCummLogChange)) - 1)),

Open in new window


Fernando
0
 
Fernando SotoRetiredCommented:
0
 
eb8931Author Commented:
Thanks  guys for your help.
0
 
Fernando SotoRetiredCommented:

Not a problem, always glad to help.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.