c# - 在 EF 6.4.4 的查询中使用多种方法
问题描述
我有在查询中使用的扩展方法。以下是方法:
public static class UOMExtensions
{
public static UOM GetSourceUOM(this UOM uOM)
{
//Calculate something
return uOM;
}
public static UOM GetParentUOM(this UOM uOM)
{
var sourceUOM = uOM.GetSourceUOM();
//Do something recoursively
return sourceUOM;
}
public static bool IsCorrectUOM(this UOM uOM)
{
var parent = uOM.GetParentUOM();
//Do something
return true;
}
}
这是我的查询:
using (Context context = new Context())
{
var uoms = context.Set<UOM>().Where(a => a.IsCorrectUOM()).ToList();
}
我得到了这个例外:
System.NotSupportedException: 'LINQ to Entities 无法识别方法'Boolean >IsCorrectUOM(ConsoleApp1.UOM)' 方法,并且此方法无法转换为存储表达式。
之后,我尝试使用以下方法创建表达式NJection.LambdaConverter
:
public static bool IsCorrectUOMMethod(UOM uOM)
{
var parent = uOM.GetParentUOM();
//Do something
return true;
}
public static Expression<Func<UOM, bool>> IsCorrectUOMExression()
{
var lambda = Lambda.TransformMethodTo<Func<UOM, bool>>()
.From(() => IsCorrectUOMMethod)
.ToLambda();
return lambda;
}
我的查询变成了:
using (Context context = new Context())
{
var uoms = context.Set<UOM>().Where(UOMExtensions.IsCorrectUOMExression()).ToList();
}
之后我得到了这个例外:
System.NotSupportedException:“‘Block’类型的未知 LINQ 表达式。”
如何成功执行我的查询?我无法更改或删除我的方法,因为它们做复杂的事情并且有很多用途。
解决方案
您必须了解 IEnumerable 和 IQueryable 之间的区别。
一个实现 IEnumerable 的对象代表一个序列:你可以得到序列的第一个元素,一旦你得到一个元素,你就可以请求序列中的下一个元素。
在最低级别,这是使用 GetEnumerator() 并重复 MoveNext() / Current 完成的。foreach、ToList()、Any()、Count() 等将深入使用这些方法。
然而,一个 IQueryable 并不代表序列本身,它代表创建序列的潜力
为此,IQueryable 包含一个表达式和一个提供程序。表达式是对必须设置哪些数据的一般描述。Provider 知道谁必须提供数据(通常是数据库管理系统),以及使用什么语言与 DBMS(通常是 SQL)进行通信。
只要您连接返回的 LINQ 语句IQueryable<...>
,您只是在更改表达式。只有当您开始枚举时,无论是使用 GetEnumerator / MoveNext 还是更高级别:foreach、ToList 等,Expression 才会发送给 Provider,后者会将其翻译成 SQL 并执行查询。返回的数据表示为一个可枚举的序列。
问题是提供者不知道你的方法GetSourceUOM
。GetParentUOM
等。因此它不能将它们翻译成 SQL。事实上,有几个 LINQ 方法也不能使用。请参阅支持和不支持的 LINQ 方法。
回到你的问题
您可以做的是转换您的扩展方法,使其扩展IQueryable<UOM>
.
public static IQueryable<UOM> WhereCorrectUOM(this IQueryable<UOM> source)
{
IQueryable<UOM> parents = source.ToParentUoms();
// Do something with parents to decide whether to return true or false
// for example:
return parents.Where(parent => parent.IsCorrect).Any();
}
public static IQueryable<UOM> ToParentUoms(this IQueryable<UOM> source)
{
IQueryable<UOM> parentUoms = source.Select(item => ...)
return parentUoms;
}
public static IQueryable<UOM> ToSourceUoms(this IQueryable<UOM> source)
{
//Calculate something
IQueryable<UOM> sourceUoms = source.Select(item => ...)
return sourceUoms;
}
唉,你忘了提到你的实际代码,所以你必须自己填写。重要的是您只能调用支持的 LINQ 和 .NET 方法,或者您自己的IQueryable<UOM>
.
推荐阅读
- javascript - JavaScript Fetch() 不区分表单的更新和删除功能
- python - 如何在优化期间使用 Pyomo 变量结果从列表中插入一个?
- css - 如何在图片上显示文字(位置:绝对)?
- javascript - 如何使用输入和 javascript 函数重复 HTML 代码
- html - Html 按钮打桩
- matlab - 比较两个大小不兼容的数据集并删除匹配的数据
- r - 没有geom的ggforce注释?
- android - 调试 Exoplayer ERROR_CODE_IO_UNSPECIFIED
- c++ - 在 Dosbox 中安装鼠标导致段错误
- flutter - 我怎样才能透明的textformfield?