Solved

Linq to Entities does not translate Math.Exp

Posted on 2011-09-16
5
749 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
Comment Utility
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 62

Assisted Solution

by:Fernando Soto
Fernando Soto earned 250 total points
Comment Utility
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 62

Expert Comment

by:Fernando Soto
Comment Utility
0
 

Author Closing Comment

by:eb8931
Comment Utility
Thanks  guys for your help.
0
 
LVL 62

Expert Comment

by:Fernando Soto
Comment Utility

Not a problem, always glad to help.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Having an SQL database can be a big investment for a small company. Hardware, setup and of course, the price of software all add up to a big bill that some companies may not be able to absorb.  Luckily, there is a free version SQL Express, but does …
Slowly Changing Dimension Transformation component in data task flow is very useful for us to manage and control how data changes in SSIS.
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.
Viewers will learn how to use the SELECT statement in SQL to return specific rows and columns, with various degrees of sorting and limits in place.

772 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now