鉴于下面的架构,我正在尝试构建一个EF查询,该查询返回缺少必需表单的联系人。每个Contact都有一个与FormTypes集合相关的ContactType。每个联系人都必须至少有一个与其ContactType相关的FormTypes Form(在ContactForm中)。
EF从下面的linq查询生成的查询对Sql Server起作用,但不针对Oracle。
var query = ctx.Contacts.Where (c => c.ContactType.FormTypes.Select (ft => ft.FormTypeID)
.Except(c => c.Forms.Select(f => f.FormTypeID)).Any());
我正在重构数据层,以便所有针对Sql Server的EF查询也可以使用Devart的dotConnect数据提供程序对付Oracle。
Oracle抛出的错误是ORA-00904:“Extent1”。“ContactID”:标识符无效。
问题在于,Oracle显然不支持在级别2和更深层次的嵌套子查询中从查询引用表列。 Oracle抛出的行是在引用“Extent1”的“Except(或减号)”子查询中。“ContactID”。 “Extent1”是在查询的顶级定义的Contact的别名。 Here is Devart's explanation of the Oracle limitation
我为许多查询解决了这个问题的方法是重写它们,使用SelectMany()将Where()谓词中的表之间的关系移动到查询的主体中,在某些情况下使用Join( )。这往往会使发送到数据库服务器的查询变得扁平,并最小化或消除EF生成的子查询。 Here is a similar issue solved using a left outer join
列“Extent1”。“ContactID”存在,EF和Devart产生的查询的命名语法不是问题。
有关如何重写此查询的任何想法将非常感激。目标是一个查询,它返回联系人缺少的表单类型所需的FormType形式,该表单类型适用于Oracle和Sql Server。