LINQ-To-Entities可以进行扩展吗?

3
一般来说,如果我创建一个作用于实体的扩展方法:
public static MyEntity Foo(this MyEntity entity)
{
  // do something to the entity
}

不能直接在Linq-To-Entities的投影中使用,例如以下方式:

var result = myContext.MyEntities.Select(x=> x.Foo());

这样做会产生如下错误:

System.NotSupportedException: LINQ to Entities does not recognize the method 'Foo(MyEntity)' method, and this method cannot be translated into a store expression.

我完全理解为什么会出现这种错误。我的问题是:如果我可以提供一个使用表达式树的Foo实现,是否有办法将Foo添加到LINQ-to-entities所理解的操作中呢?如果有,怎么做?
注意:我当然可以像这样将其转换为列表:
var result = myContext.MyEntities.ToList().Select(x=> x.Foo());

它没有出现错误。但是我不再拥有IQueryable,而是拥有IEnumerable。如果我像这样使用它:

var result = myContext.MyEntities.ToList().Select(x=> x.Foo()).First();

如果我在获取顶部实体之前获取所有实体,然后丢弃其余的实体,这会对性能造成极大的影响。


1
你可以编写自己的IQueryProvider,包装EF的查询提供程序,识别调用Foo的表达式,并向EF提供一系列等效表达式链,以便它能够将其翻译成后端存储的语言(例如SQL)。但这并不是很有趣,也不是通用的。反正Foo到底是做什么的呢? - Sergey Kalinichenko
@MattJohnson,Foo的作用非常重要,因为你能否将逻辑推入底层数据存储取决于它。最终,你的实现将在RDBMS中执行Foo的逻辑,或者将所有内容拉入内存并在CLR中运行Foo(基本上,与你示例中的ToLost使用相同的代码路径)。然而,通常情况下,EF会给你很多非常有用的扩展点,你应该在考虑自己的IQueryProvider包装器之前先考虑这些扩展点。 - Sergey Kalinichenko
@dasblinkenlight,我明白你的意思。你能详细说明一下其他可能更有用的扩展点吗?基本上,我需要实现类似于 .Include 方法的东西,但是我需要改变 EF 创建的 SQL join 的行为。 - Matt Johnson-Pint
@Ani 我看到了这个,但我不确定它如何帮助我。我该如何实现Foo?根据那个链接中的示例,我不明白他们的QueryTranslator.Include为什么与直接使用原始的.Include方法有任何区别。 - Matt Johnson-Pint
显示剩余2条评论
1个回答

2
使用LINQKit项目,但是不使用您的方法foo,您需要编写等效的表达式树。

整洁的库 - 但所有的例子都展示了在where子句中添加条件。你能提供一个在select语句中执行投影的例子,就像我的Foo需要做的那样吗? - Matt Johnson-Pint
1
尝试这样写: Expression<Func<TEntity, TEntity>> test = (x) => x; var result = context.Collection_Of_TEntity.AsExpandable().Select(x=> test.Invoke(x)).ToList(); - Mic
这基本上做到了我最初的要求。谢谢! - Matt Johnson-Pint

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接