LINQ to实体无法识别该方法

时间:2013-02-21 21:22:53

标签: c# entity-framework iqueryable

我明白为什么我会收到以下错误,但是我不确定如何提供可以绕过它的解决方案。

{System.NotSupportedException: LINQ to Entities does not recognize the method 'Boolean IsStatus(CDAX.DataModel.ProcessStatusEnum)' method, and this method cannot be translated into a store expression.

我不想只返回IEnumerable,因为我想将过滤器转换为底层SQL语句,这样我就不会查询这么多行等等

    public override IQueryable<Session> GetQuery()
    {
        Func<Session, bool> activeSessions = (session) => !session.IsStatus(ProcessStatusEnum.Deleted);

        // these functions are causing issues.  I'm not sure how to change them to
        // work with IQueryable??   
        return base.GetQuery().Where(p => activeSessions(p) && _queryFilter.FilterOn(p.Customer));
    }

_queryFilter类是一个接口,例如:

public interface IDataQueryFilter
{
    bool FilterOn(Customer obj);
}

Customer只是我数据库中的Entity对象,具有Id,CustomerNumber等属性

Session是我数据库中的另一个Entity对象,IsStatus方法是这样的:

    public bool IsStatus(ProcessStatusEnum status)
    {
        return SessionStatus == (byte)status;
    }

我使用的条件通常非常简单,所以我相信它们应该能够转换为SQL。我想这只是因为它们属于他们无法实现的功能。我可以使用其他东西作为返回类型来使这些工作吗?

2 个答案:

答案 0 :(得分:0)

您的IsStatus方法调用无法转换为SQL。我建议您在没有方法调用的情况下手动进行状态验证。

(session) => session.Status != ProcessStatusEnum.Deleted

另一种选择是将所有实体带入内存(通过执行ToList()),但这样做会很慢。

答案 1 :(得分:0)

LINQ to Entities正试图将您的LINQ查询转换为SQL语句。它现在不是如何直接在数据库上执行自定义Func,因此它会抛出此错误。

您只需将IsStatus方法更改为session.Status == ProcessStatusEnum.Deleted,但您可能会收到有关第二个功能的错误。

“修复”这个的最简单方法是在要在数据库上执行的部分和要在内存中执行的部分之间放置.ToList()。显然,数据库越多越好。

对于您的过滤器,您可能会考虑将FilterOn更改为返回表达式树的方法:

public interface IDataQueryFilter
{
    Expression<Func<Customer, bool>> FilterOn();
}

然后,例如,如果您希望伦敦的所有客户都通过LondonCustomFilter实例传递:

public class LondonCustomFilter : IDataQueryFilter {
    Expression<Func<Customer, Bool>> FilterOn() {
        return (customer) => customer.City == "London";
    }
}