我有一个计算百分比的Ling查询。
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();
但发生了异常。
我该如何解决这个问题?
答案 0 :(得分:2)
由于您使用标识符db,我假设db是DbContext。这意味着您的linq语句将在数据库服务器端的SQL中执行,而不是在您的内存中执行(SQL或类似的东西,具体取决于您使用的数据库类型)。
如果在调试器中检查语句的类型,可以看到这个:是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
中找到