Solved

Linq to Entities does not translate Math.Exp

Posted on 2011-09-16
5
760 Views
Last Modified: 2013-12-17
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

0
Comment
Question by:eb8931
  • 3
5 Comments
 
LVL 21

Accepted Solution

by:
Craig Wagner earned 250 total points
ID: 36552115
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
 
LVL 63

Assisted Solution

by:Fernando Soto
Fernando Soto earned 250 total points
ID: 36554587
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
 
LVL 63

Expert Comment

by:Fernando Soto
ID: 36554590
0
 

Author Closing Comment

by:eb8931
ID: 36559175
Thanks  guys for your help.
0
 
LVL 63

Expert Comment

by:Fernando Soto
ID: 36562109

Not a problem, always glad to help.
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

The Delta outage: 650 cancelled flights, more than 1200 delayed flights, thousands of frustrated customers, tens of millions of dollars in damages – plus untold reputational damage to one of the world’s most trusted airlines. All due to a catastroph…
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
This video shows how to set up a shell script to accept a positional parameter when called, pass that to a SQL script, accept the output from the statement back and then manipulate it in the Shell.
Viewers will learn how to use the INSERT statement to insert data into their tables. It will also introduce the NULL statement, to show them what happens when no value is giving for any given column.

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question