Linq Exception: Function can only be invoked from linq to entities

问题描述 投票:0回答:4

我有一个

StudentReceipts
表,它存储
ReceiptNo
作为
string(001,002,003,..,099,..)

我想获取最后一张收据的详细信息,以便为下一次交易增加收据。

这是我试过的

  var _lastGeneratedRecDetails = _db.StudentReceipts
                                 .AsEnumerable()
                                 .Where(r => r.Status == true
                                             && EntityFunctions.TruncateTime(r.DueDate.Value) >= _startDate.Date
                                             && EntityFunctions.TruncateTime(r.DueDate.Value) <= _endDate.Date)                                                
                                            .OrderByDescending(x => Int32.Parse(x.ReceiptNo))
                                            .FirstOrDefault();

但是我得到以下异常

此函数只能从 linq to entities 调用

任何帮助将不胜感激。

c# entity-framework linq asp.net-mvc-4
4个回答
13
投票

通过调用

.AsEnumerable()
,您将从 Linq-To-Entities 转到 Linq-To-Object。通过调用它,您还过滤了内存中的所有结果,因此每次执行该查询时,您都会从数据库中提取整个
StudentReceipts
表,因为它通过
.AsEnumerable()
方法执行。一般规则是尽可能多地在数据库方面做:

var _lastGeneratedRecDetails = 
   _db.StudentReceipts.Where(r => r.Status == true
                       && EntityFunctions.TruncateTime(r.DueDate.Value) >= _startDate.Date
                       && EntityFunctions.TruncateTime(r.DueDate.Value) <= _endDate.Date)             
                      .AsEnumerable()                                   
                      .OrderByDescending(x => Int32.Parse(x.ReceiptNo))
                      .FirstOrDefault();

如果你这样做,你将过滤数据库中的所有内容并获取过滤后的结果。我不知道

x.ReceiptNo
是什么类型,但是在 Linq-To-Entities 中不允许调用
Int.Parse
。您可以先过滤,然后调用
AsEnumerable
,以便能够在内存中进行解析和排序。


3
投票

就我而言,在我已经用 SQL 处理了查询之后,我在后续处理语句中重新使用了包含 DbFunctions.TruncateTime 的 Func / Filter 表达式。删除它为我清除了异常实例。


1
投票

使用和

.AsQueryable()

var _lastGeneratedRecDetails = _db.StudentReceipts
                             .AsEnumerable().AsQueryable()

0
投票

我想知道为什么会出现这个错误,我记得有些 DbFunctions 工作得很好。 原因是,并非所有 DbFunctions 都是在 C# 代码中实现的

如果你看一下

TruncateTime

的“执行” https://github.com/dotnet/ef6/blob/255a32450db09a2feb07cb6199af1dcdfa189b8d/src/EntityFramework/DbFunctions.cs#L655

[DbFunction("Edm", "TruncateTime")]
public static DateTime? TruncateTime(DateTime? dateValue)
{
    throw new NotSupportedException(Strings.ELinq_DbFunctionDirectCall);
}

你可以看到为什么会抛出这个错误。它只是没有实现。

上面的代码基本上说:如果在 LINQ to Entities 中使用,则执行 SQL 函数

TruncateTime
,如果在 LINQ to Objects 中使用,则运行代码(在本例中:抛出异常)

您可以实现自己的方法,只需将上面的代码复制到您自己的类中,并将您的

DbFunctions.TruncateTime(.)
调用替换为
MyFunctions.TruncateTime(.)

这真的很烦人。我需要这个,因为有时查询会针对数据库运行,有时只在代码中运行..

当然,如果您只需要对数据库调用该函数,您完全可以使用上述解决方案

© www.soinside.com 2019 - 2024. All rights reserved.