为什么:LINQ to Entities 无法识别该方法?

Why: LINQ to Entities does not recognize the method?

我有两段代码似乎具有相同的功能,但其中一段会导致异常,而另一段却很有魅力。我想知道你能想象为什么会这样吗?

我的 Web 应用程序中有以下行导致此异常:

LINQ to Entities does not recognize the method 'System.Object FilterDeliveryAddressFields(WebApplication1.Models.DeliveryAddress)'

dynamic deliveryAddresses = (from address in db.DeliveryAddress
                             select filterDeliveryAddressFields(address)).ToList();

这里是 filterDeliveryAddressFields:

private dynamic filterDeliveryAddressFields(DeliveryAddress address)
{
    return new { address.address, address.deliverTo, address.deliverToPhoneNumber, address.id };
}

这里是 Linq-2-Sql 为 DeliveryAddress 生成的模型,它与 Subscriber:

有外键关系
public partial class DeliveryAddress
{
    public int id { get; set; }
    public int fkSubscriberId { get; set; }
    public string address { get; set; }
    public string deliverTo { get; set; }
    public string deliverToPhoneNumber { get; set; }

    public virtual Subscriber Subscriber { get; set; }
}

但是,当我将 db.DeliveryAddress 项更改为首先列出,然后再次 运行 编码时,一切顺利,没有再次发生异常。我想知道下面代码段中没有发生的第一个代码段有什么问题?

List<DeliveryAddress> addresseList = db.DeliveryAddress.ToList(); //magic trick?!
dynamic deliveryAddresses =
    (from address in addresseList
     select filterDeliveryAddressFields(address)).ToList();

实际上,您的方法无法转换为 T-SQL,Linq to Entities 无法识别所有方法,您正在寻找的 .ToList() 方法背后的魔力是,加载数据后,将使用 LINQ to Objects 对内存中已有的数据执行任何进一步的操作(例如 select)。

但是这种方法不能保证性能,因为你必须加载 你的数据进入内存,想象一下你的数据库中有很多数据,接下来会发生什么?

同意@Salah。在 LINQ to Entities 中,它首先尝试将您的查询转换为命令树并针对您的 ORM 执行。请阅读 here 您可以找到更多详细信息。

在您的第一种方法中,Linq 尝试将您的 filterDeliveryAddressFields(address)) 方法转换为命令树。这就是为什么它抱怨 LINQ to Entities does not recognize the method.

在您的第二种方法中,您针对列表或 IEnumerable<T> 执行,这意味着您使用 LINQ to Object。您可以阅读更多相关信息 here

对于您的第一个解决方案,您可以尝试另一种实现方式。只需尝试使用聚合方法来过滤结果。那么你不需要 filterDeliveryAddressFields(address)) 方法。您可以找到示例 here

类似这样的东西,(抱歉,我自己没有尝试过。这只是为了让您了解一下。)

from address in db.DeliveryAddress
select new { address.address, address.deliverTo, address.deliverToPhoneNumber, address.id };