使用实体方法的结果进行lambda表达式或linq查询过滤

Dam*_*amb 3 c# lambda linq-to-entities entity-framework

我想根据使用其属性的函数的结果来过滤我的entites.

即.我有这样的实体:

public class Lorem
{
    public int A {get;set;}
    public int B {get;set;}
    public int C {get;set;}

    public double DoMath(int externalValue)
    {
        // real implementation is longer and more complex

        if(A==B) {
          // some calculations
          return 0.2;
        }
        if(B==C) {
          // some calculations
          return 0.9;
        }
        else return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我正在查询实体,我想只获得DoMath> 0的那些实体.

// simplified scenario for example purpose
int someValue = 95;
// working with Entity Framework 4.1 Code First
var filtered = db.Lorems.Where(x=>x.DoMath(someValue) > 0);
Run Code Online (Sandbox Code Playgroud)

我收到此错误:
LINQ to Entities无法识别方法-----,并且此方法无法转换为商店表达式.

有可能让它像这样工作吗?
我在定制lambda表达式和与代表一起工作方面的技巧很差,所以我想得到一些帮助.

编辑:这是'DoMath'功能真实代码(没有评论,因为它们不是英文):

public double VypocitejPrislusnost(int value)
{
    if (A == B)
    {

        if (value <= C)
        {
            return 1;
        }
        if (value > D)
        {
            return 0;
        }
        else
        {
            double b = D - C;
            double tangens = Math.Tan(1 / b);

            double a = tangens * (D - value);

            return Math.Round(a, 2);
        }
    }

    if (C == D)
    {

        if (value >= B)
        {
            return 1;
        }
        if (value <= A)
        {
            return 0;
        }
        else
        {
            double b = B - A;
            double tangens = Math.Tan(1 / b);

            double a = tangens * (value - A);

            return Math.Round(a, 2);
        }
    }

    else
    {
        if (value >= B && value <= C)
        {
            return 1;
        }
        if (value <= A || value >= D)
        {
            return 0;
        }
        if (value > A && value < B)
        {
            double b = B - A;
            double tangens = Math.Tan(1 / b);

            double a = tangens * (value - A);

            return Math.Round(a, 2);
        }
        if (value > C && value < D)
        {
            double b = D - C;
            double tangens = Math.Tan(1 / b);

            double a = tangens * (D - value);

            return Math.Round(a, 2);
        }
        else
        {
            return 0;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它基本上计算不同场景中三角形的y坐标.我用它来计算给定值适合模糊集的程度.

Ada*_*kis 9

实体框架Where期待一个表达式树,它将被转换为一个t-sql语句.不幸的是,你的DoMath方法没有转换为t-sql,所以你必须将结果下拉到内存中,然后调用Where你的方法.原因是一旦你的结果在内存中,LINQ方法就可以处理标准委托,而不是表达式树,所以对那里的内容没有任何限制

要做到这一点,只需要AsEnumerable()Where将整个表格拉入内存的课程前面,所以只有在它相当小的情况下才这样做

var filtered = db.Lorems.AsEnumerable().Where(x => x.DoMath(someValue) > 0);
Run Code Online (Sandbox Code Playgroud)

当然,如果你能识别一些基本的情况下使用你的DoMath大于0,则可以过滤这些结果出来了前面,用一个表达式树.这将减少来自数据库的结果.然后,您可以过滤内存中的其余部分.我不知道你的DoMath方法做了什么(你暗示它比你的问题中列出的更复杂),但假设这样的事情应该有效:

var filtered = db.Lorems
                 .Where(x => x.A < 10 && x.B != x.C)
                 .AsEnumerable() 
                 .Where(x => x.DoMath(someValue) > 0);
Run Code Online (Sandbox Code Playgroud)