使用entity's方法的结果进行lambda表达式或linq查询的过滤
本文关键字:lambda 表达式 过滤 查询 linq 结果 entity 方法 使用 | 更新日期: 2023-09-27 17:50:40
我想过滤我的实体取决于一个函数的结果与他们的属性工作。
ie。我得到了这样的实体:
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;
}
}
现在我正在查询实体,我想只得到那些与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);
我得到这个错误:
LINQ to Entities不识别-----方法,该方法不能转换为store表达式。
有可能使它像这样工作吗?
我在定制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;
}
}
}
它基本上是在不同的场景中计算三角形中的y坐标。我用它来计算给定值在模糊集合中的适合程度。
实体框架的Where
期待一个表达式树,这将被转换成一个t-sql语句。不幸的是,没有从你的DoMath
方法到t-sql的转换,所以你必须把结果拉到内存中,然后调用Where
,因为你有它。原因是,一旦你的结果在内存中,LINQ方法工作在标准委托,而不是表达式树,所以没有限制什么可以放在那里
要做到这一点,只需在Where
前面添加一个AsEnumerable()
-当然,这会将整个表拉入内存,所以只有在它相当小的情况下才这样做
var filtered = db.Lorems.AsEnumerable().Where(x => x.DoMath(someValue) > 0);
当然,如果您能够识别出DoMath
不大于0的一些基本情况,则可以使用表达式树预先过滤出这些结果。这将减少来自数据库的结果。您可以然后在内存中过滤其余部分。我不知道你的DoMath
方法是什么(你暗示它比你的问题中列出的更复杂),但假设这样的东西应该起作用:
var filtered = db.Lorems
.Where(x => x.A < 10 && x.B != x.C)
.AsEnumerable()
.Where(x => x.DoMath(someValue) > 0);