Groovy 1.8 :: LINQ应用

vir*_*yes 8 linq dsl groovy

更新8/31/2011
Guillaume Laforge几乎完成了它:http://gaelyk.appspot.com/tutorial/app-engine-shortcuts#query

看起来他正在进行AST转换以实现:

alias as Entity
Run Code Online (Sandbox Code Playgroud)

位.很酷的东西,Groovy 1.8 + AST转换= JVM上的LINQ-esque查询.GL的解决方案需要更多的工作,因为我可以看到完全查询功能(如子查询,使用(字段)语法等连接),但他的Gaelyk项目显然没有必要.

编辑

作为实现纯LINQ语法的一种解决方法,我决定对别名进行def.这不是一个大问题,并消除了一个可能需要复杂的AST转换才能实现的主要障碍.

所以,而不是:

from   c as Composite
join   t as Teams
...
Run Code Online (Sandbox Code Playgroud)

我现在定义别名(注意:需要强制转换才能在字段上自动完成):

def(Teams t,Composite c,Schools s) = [Teams.new(),Composite.new(),Schools.new()]
Run Code Online (Sandbox Code Playgroud)

并使用map,join等的map语法.

from    c:Composite
join    t:Teams
...
Run Code Online (Sandbox Code Playgroud)

要解决问题#2(参见下面的原文),请将实例级别的getProperty方法添加到每个pogo别名(其范围仅限于调用它的ORM闭包,不错).我们只是在构建一个sql语句时返回字符串属性名.

[t,c,s].each{Object o-> o.metaClass.getProperty = { String k-> k } }
Run Code Online (Sandbox Code Playgroud)

取得"好"进展;-)

现在要弄清楚该怎么做"=",这很棘手,因为set属性是无效的.可能必须使用eq,neq,gt等,但是真的更喜欢文字符号,这使得更接近sql的可读性.

如果有兴趣,LINQ在幕后做了很多工作.Jon Skeet(赞美他的名字)有一个很好的回复: LINQ如何在内部工作?

原版的

一直在检查LINQ,给人留下了深刻的印象.

// LINQ example
var games =
    from t in Teams
    from g in t.Games
    where g.gameID = 212
    select new { g.gameDate,g.gameTime };


// Seeking Groovy Nirvana
latest { Integer teamID->
    from   c as Composite
    join   t as Teams
    join   s as Schools on ( schoolID = {
                     from   Teams
                     where  t.schoolID = s.schoolID } )

    where   t.teamID = "$teamID"
    select  c.location, c.gameType, s.schoolName
    group   c.gameID
    order   c.gameDate, c.gameTime
}
Run Code Online (Sandbox Code Playgroud)

所提出的Groovy版本编译得很好,如果我使用相应的POGO定义别名c,t,s,我会在字段上获得强类型IDE auocomplete,很好.然而,在LINQ附近,除了查询本身之外没有(可见的)变量定义,完全自包含且强类型,哇.

好的,那么可以在Groovy中完成吗?我想(希望)是的,但我挂了2个问题:

1)如何在没有def'ing的情况下隐式填充别名变量?目前我重写了String上的asType()所以在"from c as Composite"中,c被强制转换为Composite.很好,但IDE"认为"在闭包范围内未定义的c是一个字符串,因此在POGO字段上没有自动完成;-(

2)由于#1没有解决,我按照上面的方法定义了别名,所以我可以自动完成.很好,被黑客攻击(与LINQ相比),但确实如此.这里的问题是在"select c.location,c.gameType ..."中,我希望不对字段进行求值,而只是将"c.location"返回给ORM select方法,而不是null(这是它的默认值).getProperty()应该在这里工作,但我需要它只在从ORM范围调用时应用于pogo字段(例如orm字段特定的方法,如select,order,group等).在那里失去了一点,也许有一种方法来注释orm方法,或者只通过orm方法调用(这是上面的nirvana查询中的闭包委托)调用"特殊"pogo getProperty.

应该指出我不打算为Groovy创建一个全面的LINQ,但是这个LINQ的一个特定子集我很乐意看到发生.

bla*_*rag 0

Guillaume 使用 AST 变换的最大原因之一是“=”的问题。即使您像 Groovy 中通常那样使用 == 进行比较,从为其调用的compareTo 方法中,您也无法区分 ==、!=、<=、>=、<、> 之间的区别。在 Groovy 的后续版本中,有两种可能的途径正在讨论中。一种是对每个比较使用不同的方法,另一种是存储可以在运行时访问的最小 AST。这朝着 C# 的方向发展,是一个非常强大的工具。问题更多的是如何有效地做到这一点。