2016-11-14 57 views
0

我有一个Ling Query来计算百分比。使用Linq时的错误计算百分比

 var total = db.Schema_Details.Where(x => x.RID == sName).Select(x => new{ 
Rid = x.RID, 
Amount = Convert.ToDouble(x.Lum_Sum_Amount), 
Allocation = Convert.ToDouble(x.Allocation), 
total = ((x.Allocation/100) * x.Lum_Sum_Amount)}).ToList(); 

但发生异常。

enter image description here

我该如何解决这个问题?

+0

从错误它听起来像你变成一个双变量之一已经在DB –

+0

任何机会之一lum_sum_amount为空? – BugFinder

+2

我不确定可以在lambda中使用Concert.ToDouble。它通过ef解析成sql。您可以尝试使用ToList获取列表在where调用之后(将执行sql),然后在列表中使用select方法。让我知道它是否有效 –

回答

2

由于您使用标识符db,我假设db是一个DbContext。这意味着您的linq语句将在数据库服务器端的SQL中执行,而不是在您的内存中执行(SQL或类似的,取决于您正在使用的DB的类型)。

如果您在调试器中检查语句的类型,您可以看到以下内容:它是IQueryable还是IEnumerable? IQueryables由数据库服务器执行,IEnumerable通常在您的内存中执行。通常你的数据库服务器可以比你更快,更高效地执行你的linq语句,所以最好确保你的linq语句是IQueryable。

然而,缺点是,你的数据库服务器不知道你的任何类,函数或.NET。所以在IQueryables中,你只能使用相当简单的计算。

如果你真的需要中途某处调用一些本地函数的声明LINQ,添加AsEnumerable()到您的语句:

var myLinqResult = db. ...  // something IQueryable 
    .Where(item => ...)  // simple statement: still IQueryable 
    .Select(item => ...)  // still simple, still IQueryable 
    // now you want to call one of your own functions: 
    .AsEnumerable() 
    .Select(item => myOwnLocalFunctions(item)); 

stackoverflow: Difference between IQueryable and IEnumerable

要执行的本地函数是Convert.ToDouble。 IQueryable不知道Convert类,因此不能像IQueryable那样执行你的函数。 AsEnumerable将解决这个问题。

但是,在这种情况下,我不会建议使用AsEnumerable。在数据库上执行linq语句时,尽量避免使用本地类和函数调用。而不是Convert.ToDouble使用(double)x.Sum_Amount。您的linq-to-sql转换器(或类似的数据库语言转换器)将知道如何将其转换为IQueryable。

有一些计算其中有SQL等效项,如DateTime计算或字符串反转。如果您必须在本地内存中执行诸如DateTime.AddDays(1)之类的操作,并且存在完美的SQL等效项,那将是一件耻辱。如果您需要在您的本地功能之后加入,选择或GroupBy,这尤其会成为问题。您的数据库服务器可以比您更有效地完成这些任务。幸运的是,它们有一些IQueryable扩展功能。他们可以在System.Data.Entity.DbFunctions