查询表达式如何连接取决于键的顺序?

时间:2014-03-21 21:14:35

标签: f# f#-3.0 f#-4.0

在查询表达式的documentation中,我找到了:

  

请注意,连接表达式中=符号周围的键的顺序非常重要。

但是,我不能找到关于顺序如何重要,它有什么区别,或者使相等运算符非对称的基本原理的任何信息。

任何人都可以解释或指出一些更好的文档吗?

2 个答案:

答案 0 :(得分:1)

这对于连接非常重要。例如,如果您查看leftOuterJoin的示例:

query {
    for student in db.Student do
    leftOuterJoin selection in db.CourseSelection on
                   (student.StudentID = selection.StudentID) into result
    for selection in result.DefaultIfEmpty() do
    select (student, selection)
    }

订单确定发生“缺失”值时会发生什么。关键是文档中的这一行:

  

如果任何组为空,则使用具有单个默认值的组。

使用当前订单,即使StudentID没有匹配的元素,也会表示db.Student内的每个db.CourseSelection。如果您颠倒顺序,则情况恰恰相反 - 将显示每个“课程选择”,缺少students获取默认值。这意味着,在上面,如果你改变了顺序,任何没有选择课程的学生都不会在结果中有任何表示,当前的顺序总是显示每个学生。

答案 1 :(得分:1)

运算符左侧的表达式必须来自"外部"正在加入的东西和右边的表达必须来自"内部"事情(正如你在评论Reed&#39的回答中提到的那样)。这是因为LINQ API - 用于构建查询的实际方法看起来像this

static member Join<'TOuter, 'TInner, 'TKey, 'TResult> : 
    outer:IQueryable<'TOuter> *
    inner:IEnumerable<'TInner> *
    outerKeySelector:Expression<Func<'TOuter, 'TKey>> *
    innerKeySelector:Expression<Func<'TInner, 'TKey>> *
    resultSelector:Expression<Func<'TOuter, 'TInner, 'TResult>> -> IQueryable<'TResult>

所以你不能加入任意布尔表达式(你可以在SQL中做 - 像JOIN ON a.x + b.y - 7 > a.w * b.z这样的东西在SQL中很好但在LINQ中没有),你只能基于两者之间的相等条件加入外表和内表的显式投影。在我看来,这是一个非常不幸的设计决定,但它已经从LINQ转移到F#。