使用Func作为LinqToEntities的参数 [英] Using Func as parameter for LinqToEntities

查看:213
本文介绍了使用Func作为LinqToEntities的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Linq-Query来获取我的EF-Data。我的查询连接4个表,并将结果选择为非规范化类型。我会经常需要这个查询,但使用不同的谓词。 List-ExtensionMethods(例如 .Where()正在使用 Func< T,bool> 作为参数,我想要这样做 - 但是我没有找到一种方法来访问我的方法中的谓词。

  public DenormalizedType GetData(Func< Thing,bool>谓词)
{
using(var dbContext = new MyDbContext())
{
var myData =(from some in dbContext.Thing
加入其他的dbContext.OtherThing
在some.OtherId等于other.Id
// => HowToWhere ???
选择新的DenormalizedType()
{
SomeEntry = some.Entry
SomeOtherId = some.OtherId
OtherValue = other.Value
})ToList();
}
}

我有3个有关此问题的问题。



):如何调用我的谓词来使用动态的where子句?



第二:如果我的ini tial想法不工作(因为teovankots的答案表明,我的方法对于LinqToEntities不是有效的)是否有可能,只提供一种加入方法?



第三:将结果返回到另一个软件组件是最好的方法是什么?

解决方案

EF查询提供者需要将LINQ查询表达式树转换为SQL,当您传递 Func< ...> (和更一般地,调用表达式,如委托,未知方法等)。



不久之后,您无法使用 Func< ...> 类型参数。



使用 Queryable 方法时要考虑的第一件事是使用 Expression< Func< .. 。>> 每当您在 Enumerable 中使用 Func< ..> 方法。所以改变你的方法参数:

  public DenormalizedType GetData(Expression< Func< Thing,bool>> predicate)

不幸的是,使用LINQ查询语法中提供的表达式不支持开箱即用。要做到这一点,你需要一些表达式树处理库。



问题和可能的解决方案在 LINQKit 包页面。软件包提供的解决方案是通过 AsExpandable 调用自定义扩展方法。



安装 nuget包,添加

 使用LinqKit; 

到源代码文件,现在可以使用这样的东西来实现目标: p>

  public DenormalizedType GetData(Expression< Func< Thing,bool>> predicate)
{
using dbContext = new MyDbContext())
{
var myData =(从dbContext.Thing.AsExpandable()中的一些)// <=
在dbContext.OtherThing
中加入其他some.OtherId等于other.Id
其中predicate.Invoke(some)//< =
select new DenormalizedType()
{
SomeEntry = some.Entry
SomeOtherId = some.OtherId
OtherValue = other.Value
})ToList();
}
}


I have a Linq-Query to get my EF-Data. My query joins 4 tables and selects the result to a denormalized type. I will need this query very often but with different predicates. The List-ExtensionMethods (e.g. .Where() are working with a Func<T,bool> as a parameter and I wanted to do it the same - but I don´t find a way to access my predicate in my Method.

public DenormalizedType GetData(Func<Thing, bool> predicate)
{
    using (var dbContext = new MyDbContext())
    { 
        var myData = (from some in dbContext.Thing 
        join other in dbContext.OtherThing
        on some.OtherId equals other.Id
        // => HowToWhere ???
        select new DenormalizedType()
        {
            SomeEntry = some.Entry
            SomeOtherId = some.OtherId
            OtherValue = other.Value
        }).ToList();
    }
}

I have 3 questions regarding this issue.

First (obviously): how to invoke my predicate to use a dynamic where-clause?

Second: If my initial idea doesn´t work (because teovankots answer indicates, that my approach isn´t valid for LinqToEntities) is it somehow possible, to make a method of the join only?

Third: What is the best performing approach to return my results to another software-component?

解决方案

EF query provider needs to translate the LINQ query expression tree to SQL, which is not possible when you pass a Func<...> (and more generally, invocation expression like delegate, unknown method etc.).

Shortly, what you ask is not possible with Func<...> type parameters.

The first thing to consider when working with Queryable methods is to use Expression<Func<...>> whenever you would use Func<..> in Enumerable methods. So change your method argument like this:

public DenormalizedType GetData(Expression<Func<Thing, bool>> predicate)

Unfortunately using the supplied expression inside LINQ query syntax is not supported out of the box. To do that, you need some expression tree processing library.

The problem and the possible solution is explained in the LINQKit package page. The solution provided by the package is through AsExpandable and Invoke custom extension methods.

Install the nuget package, add

using LinqKit;

to the source code file, and now you can use something like this to achieve the goal:

public DenormalizedType GetData(Expression<Func<Thing, bool>> predicate)
{
    using (var dbContext = new MyDbContext())
    { 
        var myData = (from some in dbContext.Thing.AsExpandable() // <= 
        join other in dbContext.OtherThing
        on some.OtherId equals other.Id
        where predicate.Invoke(some) // <=
        select new DenormalizedType()
        {
            SomeEntry = some.Entry
            SomeOtherId = some.OtherId
            OtherValue = other.Value
        }).ToList();
    }
}

这篇关于使用Func作为LinqToEntities的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆