如何将前pression树转换为偏SQL查询? [英] How to convert an expression tree to a partial SQL query?

查看:279
本文介绍了如何将前pression树转换为偏SQL查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在EF或LINQ to SQL中运行一个查询时,它:

When EF or LINQ to SQL runs a query, it:


  1. 构建从code。将前pression树,

  2. 除权pression树转换为SQL查询,

  3. 执行查询,从数据库获取的原始结果,并将其转换到结果要由应用程序使用。

看着堆栈跟踪,我无法揣摩出的第二部分发生的。

Looking at the stack trace, I can't figure out where the second part happens.

在一般情况下,是有可能使用EF的存在部分或(preferably),LINQ to SQL来一个防爆pression 对象转换为部分SQL查询(使用Transact-SQL语法),或者我要推倒重来?

In general, is it possible to use an existent part of EF or (preferably) LINQ to SQL to convert an Expression object to a partial SQL query (using Transact-SQL syntax), or I have to reinvent the wheel?

更新:评论要求提供的什么,我试图做一个例子

Update: a comment asks to provide an example of what I'm trying to do.

其实,<一个href=\"http://stackoverflow.com/questions/7731905/how-to-convert-an-ex$p$pssion-tree-to-a-partial-sql-query/7891426#7891426\">the赖安·赖特下面答案完全说明我想达到的结果,但事实上,我的问题是具体什么的我怎么可以用实际使用的EF .NET Framework的存在机制,做到这一点, LINQ to SQL的的,而不必另起炉灶写成千上万不那么测试$ C $的行C自己做类似的事情。

Actually, the answer by Ryan Wright below illustrates perfectly what I want to achieve as a result, except the fact that my question is specifically about how can I do it by using existent mechanisms of .NET Framework actually used by EF and LINQ to SQL, instead of having to reinvent the wheel and write thousands of lines of not-so-tested code myself to do the similar thing.

下面也是一个例子。再次提醒,没有ORM生成code。

Here is also an example. Again, note that there is no ORM-generated code.

private class Product
{
    [DatabaseMapping("ProductId")]
    public int Id { get; set; }

    [DatabaseMapping("Price")]
    public int PriceInCents { get; set; }
}

private string Convert(Expression expression)
{
    // Some magic calls to .NET Framework code happen here.
    // [...]
}

private void TestConvert()
{
    Expression<Func<Product, int, int, bool>> inPriceRange =
        (Product product, int from, int to) =>
            product.PriceInCents >= from && product.PriceInCents <= to;

    string actualQueryPart = this.Convert(inPriceRange);

    Assert.AreEqual("[Price] between @from and @to", actualQueryPart);
}

哪里的名称价格来自于预期的查询?

Where does the name Price come from in the expected query?

该名称可以通过反射通过查询定制 DatabaseMapping 价格属性的属性<$ C $得到C>产品类。

The name can be obtained through reflection by querying the custom DatabaseMapping attribute of Price property of Product class.

在哪里名称 @from @至来自于预期的查询?

Where do names @from and @to come from in the expected query?

这些名称都是前pression参数的实际名称。

Those names are the actual names of the parameters of the expression.

哪里之间...和来自于预期的查询?

Where does between … and come from in the expected query?

这是一个二进制的前pression的可能结果。 ...和语句之间也许EF或LINQ到会的SQL,而不是,坚持使用 [参考价格]&GT; = @from和[参考价格]&LT; = @至来代替。这也没关系,这并不重要,因为结果在逻辑上是相同的(我不提性能)。

This is a possible result of a binary expression. Maybe EF or LINQ to SQL would, instead of between … and statement, stick with [Price] >= @from and [Price] <= @to instead. It's ok too, it doesn't really matter since the result is logically the same (I'm not mentioning performance).

为什么没有,其中在预期查询?

Why there is no where in the expected query?

由于没有证据表明在防爆pression 必须有一个其中,关键字。也许实际的前pression只是前pressions以后将与二元运算结合起来,建立以prePEND以其中,

Because nothing indicates in the Expression that there must be a where keyword. Maybe the actual expression is just one of the expressions which would be combined later with binary operators to build a larger query to prepend with a where.

推荐答案

简短的回答似乎是你不能使用EF或LINQ的的部分的到SQL的快捷方式转换。你至少需要的ObjectContext 的一个子类来获得在内部保护 QueryProvider属性,这意味着创建上下文,包括所有的元数据等的所有的开销。

The short answer seems to be that you cannot use a part of EF or LINQ to SQL as a shortcut to translation. You need at least a subclass of ObjectContext to get at the internal protected QueryProvider property, and that means all the overhead of creating the context, including all the metadata and so on.

假设你是行这一说法,得到了部分的SQL查询,例如,在 WHERE 子句你基本上将需要查询供应商和呼叫< A HREF =htt​​p://msdn.microsoft.com/en-us/library/bb549043.aspx> IQueryProvider.CreateQuery()只是作为的LINQ确实在其实施的Queryable.Where 。为了让你可以使用更完整的查询<一个href=\"http://msdn.microsoft.com/en-us/library/system.data.objects.objectquery.totracestring.aspx\">ObjectQuery.ToTraceString().

Assuming you are ok with that, to get a partial SQL query, for example, just the WHERE clause you're basically going to need the query provider and call IQueryProvider.CreateQuery() just as LINQ does in its implementation of Queryable.Where. To get a more complete query you can use ObjectQuery.ToTraceString().

至于到这种情况, LINQ提供基本国家普遍认为

As to where this happens, LINQ provider basics states generally that

IQueryProvider返回与构成前$ P $由LINQ框架,其用于进一步的呼叫传递pssion树的引用的IQueryable。概括地说,每个查询块被转换成一串的方法调用。对于每一个方法调用,也有参与一些前pressions。同时创造我们的供应商 - 在方法IQueryProvider.CreateQuery - 我们通过前pressions运行,填补了一个过滤器对象,这是在IQueryProvider.Execute方法用来运行对数据存储的查询

IQueryProvider returns a reference to IQueryable with the constructed expression-tree passed by the LINQ framework, which is used for further calls. In general terms, each query block is converted to a bunch of method calls. For each method call, there are some expressions involved. While creating our provider - in the method IQueryProvider.CreateQuery - we run through the expressions and fill up a filter object, which is used in the IQueryProvider.Execute method to run a query against the data store

查询可以以两种方式,或者通过实施在查询类GetEnumerator方法(在IEnumerable接口定义),(其中从IQueryable的继承)执行;或者它可以由LINQ运行时直接执行

the query can be executed in two ways, either by implementing the GetEnumerator method (defined in the IEnumerable interface) in the Query class, (which inherits from IQueryable); or it can be executed by the LINQ runtime directly

在调试器下检查EF是前者。

Checking EF under the debugger it's the former.

如果您不想完全重新发明轮子既不EF也不LINQ to SQL中的选择,也许是本系列文章将帮助:

If you don't want to completely re-invent the wheel and neither EF nor LINQ to SQL are options, perhaps this series of articles would help:

  • How to: LINQ to SQL Translation
  • How to: LINQ to SQL Translation - Part II
  • How to: LINQ to SQL Translation - Part III

下面是一些源创建一个查询提供商可能涉及您的部分更加繁重实现你想要什么:

Here are some sources for creating a query provider that probably involve much more heavy lifting on your part to implement what you want:

  • LINQ: Building an IQueryable provider series
  • Creating custom LINQ provider using LinqExtender

这篇关于如何将前pression树转换为偏SQL查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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